You are running into a subtle issue with how POSIX systems handle killing processes.
When the process is killed, then the kernel redefines who the parent is. Unlike when a child exits and notifies its parent, if the parent process does not send a signal down to the child on exit, then the child receives no notification. The kernel simply redefines its parent id to the init process.
Therefore, by default no child exits when it's parent exits. So how do children get killed at all when a parent quits? Well, every process has a process group id. This defaults to the process group id of it's parent on start. If a process group becomes orphaned by the death of a process, then the kernel might send a SIGHUP
and SIGCONT
to all members of the process group. This gives the children a chance to exit, but they don't have to. If they do not quit, then they are orphaned processes, and they get their parent id set to the init process.
Coincidentally, this is how forking to create a daemon process works.
So, to resolve your problem, make sure that the grandchildren are part of the same process group id. This should let them receive the signal that kills the child process. However, if they ignore the signal, you really only have one option.
Spawn a wrapper program that does nothing but spawn your actual process and passes everything back and forth between the "real" parent and the "real" child. Then, if the SIGHUP
gets sent to your wrapper, send a SIGKILL
to the child to force an exit.