1

I have a python process, which spawns a git (git clone) child process, which in turn spawns several child processes itself. Here, I want to kill all processes in the process tree rooted by git, without killing the python process.

Possible solutions with caveats:

  • Traverse the child process tree of python using /proc/<pid> recursively.

In this case, how can I be sure that any process in this process hierarchy hasn't spawned a child process before it being killed, in which case the child becomes an orphan (race condition)?

  • Kill the process group of the python process, which includes git and every other descendant.

In this case, python process is killed too, which I don't want to happen.

Is there any way to reliably kill all processes in the process hierarchy rooted by the python process, but not the python process itself?

AdminBee
  • 22,803
Shuzheng
  • 4,411
  • @terdon - sorry for my bad phrase of the problem. I've completed rewritten the question. Tell me, if you miss any details. – Shuzheng Oct 04 '20 at 15:53
  • Much better, thanks! Now, to make it perfect, can you give us a minimal example that we can run and test our answers? That would be very useful in trying to debug this. – terdon Oct 04 '20 at 16:12
  • 1
    You create a separate process group and put all children in it. And take care to catch and forward the INT signal to the new process group. You should do that not because a kill -pgid will also kill your python (you can just catch the signal), but because it also kill other sibling or parent processes of your python (as any script it was called from, or other processes from the same pipeline). Generally, if you have to care too much about process management and you're not writing the next systemd, it's probably because you're overcomplicating yourself. –  Oct 05 '20 at 06:33
  • @StephenKitt The OP already had 2 descendants. –  Oct 05 '20 at 07:33

1 Answers1

1

The pslist package contains rkill which can kill all descendants:

man pslist:

The pslist utility examines the list of current processes to find a specified process and all its descendants. [..]

When invoked as rkill, this utility does not display information about the processes, but sends them all a signal instead. If not specified on the command line, a terminate (SIGTERM) signal is sent.

You only need to give it the pid of git.

(available on ubuntu/arch/etc.)

laktak
  • 5,946
  • Is it possible that a race condition exist, where a process spawns a child after rkill has done its examination of descendants, but before it has been killed, in which case the child becomes an orphan? – Shuzheng Oct 05 '20 at 06:22
  • I only looked at the source briefly (https://devel.ringlet.net/sysutils/pslist/) - it first collects the pids (proc_get_children_r) and only then kills them. So yes, a race condition is possible with this tool. – laktak Oct 05 '20 at 07:26
  • I know it's off-topic, but will any approach for killing a process tree not be subject to such race condition, when executed from userland? I guess only the kernel will be able to restrict the processes from creating new children, while it kills them. – Shuzheng Oct 05 '20 at 08:41
  • I don't think that's possible. Because if you kill the parent process first, each of children will become orphan, which result in init(8) becomming the new parent process for those children. Thus, you loose the ppid information. – Shuzheng Oct 05 '20 at 10:41
  • Yes, you are correct. This question has already been answered, although not the part about the race condition https://unix.stackexchange.com/questions/124127/kill-all-descendant-processes – laktak Oct 05 '20 at 13:03