0

I have a Python server that starts multiple subprocesses via subprocess.Popen(). When I run a specific method on the server, I want to terminate all of these processes.

My approach to this was to keep references to all processes in a list ...

self.procs.append(subprocess.Popen(shlex.split(cmd)))

... and send interrupts to all of these to shut them down:

for i, p in enumerate(self.procs) :
    p.send_signal(signal.SIGINT)
    print 'interrupted ' + str(i)
self.procs = []

However, this only works for some of the subprocesses. For instance, one of the processes that does not stop after this call is a bash script that has a trap function for SIGINT signals. If I manually start this script and interrupt it via keyboard, it correctly executes the trap statement and closes . When the server sends the signal instead, the script seems to keep running.

What could be going wrong here?

edit: I have also tried using the SIGTERM signal instead, which did not work either.

zinfandel
  • 428
  • 5
  • 12
  • The usual signal to send for a shutdown is `SIGTERM`. Often we might have a "grace-time" delay and send SIGKILL (like `kill -9`) if the process still has not closed. The interrupt might not work if the script is waiting on a child process to complete at the time. – cdarke Sep 09 '15 at 12:20
  • I have also tried `SIGTERM` which still did not solve my problem. Also, I assume my problem has its root elsewhere since my bash script traps `SIGINT` specifically, but does not seem to execute the trap statement when getting the signal from the server. – zinfandel Sep 09 '15 at 12:24
  • 1
    Did you try `p.terminate()` or `p.kill()`? – cdarke Sep 09 '15 at 12:28
  • 2
    Try to group all processes in a group and kill it. as mentionned here. http://stackoverflow.com/questions/4789837/how-to-terminate-a-python-subprocess-launched-with-shell-true. – Ali SAID OMAR Sep 09 '15 at 14:28
  • if you want to kill a process tree then use [the solution from @AliSAIDOMAR 's comment](http://stackoverflow.com/a/4791612/4279) (if you don't need to shutdown the processes gracefully; you could send SIGKILL immediately) – jfs Sep 10 '15 at 10:46
  • I just resolved my problem thanks to Ali's comment, thank you all. I answered my own question for other people searching up on the topic. – zinfandel Sep 10 '15 at 16:25

1 Answers1

1

Thanks everyone for your contributions, what worked for me in the end was the approach that Ali linked. I started all subprocesses with this additional parameter:

preexec_fn=os.setpgrp

And then called

os.killpg(p.pid, signal.SIGTERM)

SIGTERM, SIGINT, kill() or terminate() alone did not work for my shell script. The script was internally starting two services (sudo service start) and was supposed to sudo service stop them in a trap function, which did not work as expected.

I actually had some more trouble with another process that wouldn't shut down - a Python server that was not deployed but simply started as a script. No idea why the killpg approach did not work with this one. I finally resolved the issue by having it write its pid to a file and later have the parent script read it out and kill that pid.

zinfandel
  • 428
  • 5
  • 12