But the issue here is more basic than timeouts. If we are to use process groups in the example, then B must be a process group leader for C and simultaneously belong to the process group led by A, which is impossible on Unix—that’s what TFA means by “[the] process group mechanism [is] one-level deep”. Close but no cigar.
(On the other hand, no reason this can’t be an extension to—I would even say a rationalization of—the process group mechanism. It doesn’t exist right now, though.)
A harder problem is making sure that the program shuts down if some thread panics. There are several ways to do that, but it's not automatic.
Incidentally, regular mutexes are "poisoned" if the thread holding them panics. Anyone trying to lock the mutex gets an error. However, parking_lot mutexes do not do this. If the thread holding one of those panics, the mutex unlocks. This may be unsafe.
The process group mechanism may be one of the less well-known parts of UNIX.
> There’s process group mechanism, but it is one-level deep and is mostly reserved for the shell.
So the author seems aware that they exist, at least
I've come across programs that use SIGHUP for various things like config reloading when they could use USR1/USR2 instead. UNIX signals are kind of crap in my opinion. USR1/USR2 should probably not even exist, there should be some other way to 'message' processes without IPC.
Shells push each job into a separate group, making the shell interpreter the process group leader. Thats why suspend works, it sends that whole process group to the background.
Depending on how an interpreter is setup a shell script might end up under its own progress group if the shell always creates one... usually when invoked as an interpreter it shouldn't be making a new one though.
I'm assuming all processes are under your control in this scenario. It should be very rare for any process that isn't a shell or daemon to create its own process group or session.
Sessions can optionally have a controlling terminal, one (and only one) foreground process group, plus any number of background process groups.
The foreground job is how the system decides who receives signals generated by the TTY. If the controlling TTY disconnects or is closed the session leader gets SIGHUP which it usually uses to signal all the process groups it created. If the session leader dies or exits then all processes in the foreground process group get a SIGHUP.
If you exit an interactive shell or close your SSH session the system generally cleans everything up as you would expect. The processes involved generally don't implement any special handling code to make this happen: the session leader (your login shell) uses the standard Unix job control APIs to manage the session + process groups and the expected behavior falls out naturally.
Unless there is a good reason to implement this differently: don't. Use the standard Unix job control APIs as they were designed to be used.
Which is my point. It can't really be used as a generic mechanism for killing all child processes.