Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to kill a python child process created with subprocess.check_output() when the parent dies?

I am running on a linux machine a python script which creates a child process using subprocess.check_output() as it follows:

subprocess.check_output(["ls", "-l"], stderr=subprocess.STDOUT) 

The problem is that even if the parent process dies, the child is still running. Is there any way I can kill the child process as well when the parent dies?

like image 875
Clara Avatar asked Oct 18 '13 10:10

Clara


People also ask

How do you kill a child process in Python?

You can kill all child processes by first getting a list of all active child processes via the multiprocessing. active_children() function then calling either terminate() or kill() on each process instance.

How do you kill a process using the child process?

Using the timeout Command. For killing a child process after a given timeout, we can use the timeout command. It runs the command passed to it and kills it with the SIGTERM signal after the given timeout. In case we want to send a different signal like SIGINT to the process, we can use the –signal flag.

How do you kill a process in python?

A process can be killed by calling the Process. kill() function. The call will only terminate the target process, not child processes.

How do you stop a subprocess run in Python?

To close a single subprocess in Python, use the kill() method. The kill() is a built-in method used for terminating a single subprocess. The kill() command keeps running in the background.


1 Answers

Yes, you can achieve this by two methods. Both of them require you to use Popen instead of check_output. The first is a simpler method, using try..finally, as follows:

from contextlib import contextmanager  @contextmanager def run_and_terminate_process(*args, **kwargs): try:     p = subprocess.Popen(*args, **kwargs)     yield p         finally:     p.terminate() # send sigterm, or ...     p.kill()      # send sigkill  def main():     with run_and_terminate_process(args) as running_proc:         # Your code here, such as running_proc.stdout.readline() 

This will catch sigint (keyboard interrupt) and sigterm, but not sigkill (if you kill your script with -9).

The other method is a bit more complex, and uses ctypes' prctl PR_SET_PDEATHSIG. The system will send a signal to the child once the parent exits for any reason (even sigkill).

import signal import ctypes libc = ctypes.CDLL("libc.so.6") def set_pdeathsig(sig = signal.SIGTERM):     def callable():         return libc.prctl(1, sig)     return callable p = subprocess.Popen(args, preexec_fn = set_pdeathsig(signal.SIGTERM)) 
like image 177
micromoses Avatar answered Sep 20 '22 16:09

micromoses