3

I'm struggling with some processes I started with Popen and which start subprocesses. When I start these processes manually in a terminal every process terminates as expected if I send CTRL+C. But running inside a python program using subprocess.Popen any attempt to terminate the process only gets rid of the parent but not of its children.

I tried .terminate() ..kill() as well as ..send_signal() with signal.SIGBREAK, signal.SIGTERM, but in every case I just terminate the parent process.

With this parent process I can reproduce the misbehavior:

#!/usr/bin/python

import time
import sys
import os
import subprocess
import signal

if __name__ == "__main__":
  print os.getpid(), "MAIN: start a process.."
  p = subprocess.Popen([sys.executable, 'process_to_shutdown.py'])
  print os.getpid(), "MAIN: started process", p.pid
  time.sleep(2)
  print os.getpid(), "MAIN: kill the process"
  # these just terminate the parent:
  #p.terminate()
  #p.kill()
  #os.kill(p.pid, signal.SIGINT) 
  #os.kill(p.pid, signal.SIGTERM)
  os.kill(p.pid, signal.SIGABRT)
  p.wait()
  print os.getpid(), "MAIN: job done - ciao"

The real life child process is manage.py from Django which spawns a few subprocesses and waits for CRTL-C. But the following example seems to work, too:

#!/usr/bin/python

import time
import sys
import os
import subprocess

if __name__ == "__main__":

    timeout = int(sys.argv[1]) if len(sys.argv) >= 2 else 0

    if timeout == 0:
        p = subprocess.Popen([sys.executable, '-u', __file__, '13'])
        print os.getpid(), "just waiting..."
        p.wait()

    else:
        for i in range(timeout):
            time.sleep(1)
            print os.getpid(), i, "alive!"
            sys.stdout.flush()

    print os.getpid(), "ciao"

So my question in short: how do I kill the process in the first example and get rid of the child processes as well? On windows os.kill(p.pid, signal.CTRL_C_EVENT) seems to work in some cases, but what's the right way to do it? And how does a Terminal do it?

Uli Klank
  • 199
  • 10
frans
  • 8,868
  • 11
  • 58
  • 132
  • 1
    Have you tried to use group process as suggested in this thread? http://stackoverflow.com/questions/4789837/how-to-terminate-a-python-subprocess-launched-with-shell-true – Henri Korhonen Sep 13 '13 at 20:20

1 Answers1

0

Like Henri Korhonen mentioned in a comment, grouping processes should help. Additionally, if you are on Windows and this is Cygwin Python that starts Windows applications, it appears Cygwin Python can not kill the children. For those cases you would need to run TASKKILL. TASKKILL also takes a group parameter.

Heikki Toivonen
  • 30,964
  • 11
  • 42
  • 44