kill subprocess using signal.CTRL_C_EVENT without killing main

Viewed 718

How can I kill a subprocess without also killing main?

I have a subprocess that can only be killed with signal.CTRL_C_EVENT. Performing the standard os.kill(my_pid, signal.CTRL_C_EVENT) kills the process but also causes my main to die despite having a differnet pid.

My ultimate goal is to create the subprocess from within a unit test so i need the unit test to return sys.exit(0) after passing all tests.

child.py

from time

while True:
  print "I am alive"
  time.sleep(0.5)

parent.py

import os
import signal
import subprocess
import time

p = subprocess.Popen(["child.py"], shell=True)
time.sleep(5)
os.kill(p.pid, signal.CTRL_C_EVENT)

print("This line doesn't print because the main thread dies")

::: update :::

I am trying to run this in Windows. removing shell=True has no apparent effect. I am seeing a KeyboardInterrupt error in parent.py

Traceback (most recent call last)    
    File "parent.py", line 23, in <module>
KeyboardInterrupt

All of the following methods result in this same behavior

  • os.kill
  • send signal on psutil.Process(os.getpid()).children()
  • subprocess.call(['taskkill', ...
2 Answers

I take it you are on Windows. That is an important distinction here. It also appears you are using Python2.

On Windows, os.kill has some really strange behavior. I'd suggest not even trying to use it, unless you are trying to give yourself a headache. Try usingf psutil (in the parent):

    children = psutil.Process(os.getpid()).children()
    for c in children:
        c.send_signal(signal.CTRL_C_EVENT)
    psutil.wait_procs(children)

alternately, you can call taskkill:

subprocess.call(['taskkill', '/PID', str(child.pid)])

You can try sending the byte 0x03 to the child process's standard input (stdin). This is the byte used to indicate a Ctrl+C signal.

Related