6

I am writing code to kill a process and all children processes.

According to this post, all children processes can be killed within the same process group by using os.killpg(pro.pid, signal.SIGTERM)

During test, I launched this process manually which spawned 5 subprocesses.

    UID      PID  PPID  C STIME TTY          TIME CMD
    ddd    25066 19475  0 Nov03 ?        00:00:00 /bin/sh -c gtdownload -c ~/.cghub.key --max-children 4 -vv -d https://cghub.ucsc.edu/cghub/data/analysis/download/ab0e89b4-5310-11e4-88da-adc9fc308db6 2
    ddd    25067 25066  0 Nov03 ?        00:00:07 /rsrch1/rists/djiao/apps/cghub/libexec/gtdownload -c /rsrch1/rists/djiao/.cghub.key --max-children 4 -vv -d https://cghub.ucsc.edu/cghub/data/analysis/d
    ddd    25073 25067  0 Nov03 ?        00:00:18 /rsrch1/rists/djiao/apps/cghub/libexec/gtdownload -c /rsrch1/rists/djiao/.cghub.key --max-children 4 -vv -d https://cghub.ucsc.edu/cghub/data/analysis/d
    ddd    25077 25067  0 Nov03 ?        00:00:18 /rsrch1/rists/djiao/apps/cghub/libexec/gtdownload -c /rsrch1/rists/djiao/.cghub.key --max-children 4 -vv -d https://cghub.ucsc.edu/cghub/data/analysis/d
    ddd    25081 25067  0 Nov03 ?        00:00:18 /rsrch1/rists/djiao/apps/cghub/libexec/gtdownload -c /rsrch1/rists/djiao/.cghub.key --max-children 4 -vv -d https://cghub.ucsc.edu/cghub/data/analysis/d
    ddd    25085 25067  0 Nov03 ?        00:00:18 /rsrch1/rists/djiao/apps/cghub/libexec/gtdownload -c /rsrch1/rists/djiao/.cghub.key --max-children 4 -vv -d https://cghub.ucsc.edu/cghub/data/analysis/d

However when I ran os.killpg(25066, signal.SIGTERM), I got the error "OSError: [Errno 3] No such process". Why can't it find the process with that ID?

Community
  • 1
  • 1
Nasreddin
  • 1,509
  • 9
  • 31
  • 36
  • In the linked post, did you see how they called `Popen`? In particular, the `preexec_fn=os.setsid` is important. – Colonel Thirty Two Nov 04 '15 at 18:16
  • I thought that step is just to initiate the process. Once it is started it will have a PID assigned anyway. In my real code I did use Popen with setsid. I just wanted to test the killpg first and see what it actually kills – Nasreddin Nov 04 '15 at 18:41
  • 2
    `killpg` sends a signal to all of the processes in a process group, and takes a process group ID. `setsid` creates a new process group, with its id equal to the process's PID. If you don't run `setsid`, there will be no process group for `killpg` to send to (hence the error). – Colonel Thirty Two Nov 04 '15 at 18:46

2 Answers2

1

You need to set process group using os.setpgrp() before calling os.killpg(). If you don't set any process group then you won't be able to kill it using os.killpg()

You can create process group using following ways:

  1. os.setpgrp() -- If no argument is passed then it is equivalent to os.setpgrp(0,0). This will create a process group with id same as the calling process id.
  2. os.setpgrp(0, 999) -- It will create a process group with id 999 and the current process will be part of that group. You can use any process id instead of 0 to make it part of that process group.

os.setpgrp() actually calls linux system call setpgrp(). See following linux man page for detail: https://linux.die.net/man/2/setpgrp

http://man7.org/linux/man-pages/man2/setpgid.2.html

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Vivek Agrawal
  • 113
  • 11
1

I had a similar issue and following the recommendations from this answer I fixed it by adding preexec_fn=os.setsid to the Popen call this way the created processes form a new process group and all the children it creates later belongs to this same session. This way you can kill the process and its children by calling os.killpg on the created process session id.

For example you can create your process as following:

p = subprocess.Popen('sleep  53 & sleep  54 | sleep  56', shell=True, preexec_fn=os.setsid)
... do whatever ..
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
rkachach
  • 16,517
  • 6
  • 42
  • 66