Kill or terminate subprocess when timeout? Kill or terminate subprocess when timeout? python python

Kill or terminate subprocess when timeout?


You could do something like this:

import subprocess as subimport threadingclass RunCmd(threading.Thread):    def __init__(self, cmd, timeout):        threading.Thread.__init__(self)        self.cmd = cmd        self.timeout = timeout    def run(self):        self.p = sub.Popen(self.cmd)        self.p.wait()    def Run(self):        self.start()        self.join(self.timeout)        if self.is_alive():            self.p.terminate()      #use self.p.kill() if process needs a kill -9            self.join()RunCmd(["./someProg", "arg1"], 60).Run()

The idea is that you create a thread that runs the command and to kill it if the timeout exceeds some suitable value, in this case 60 seconds.


Here is something I wrote as a watchdog for subprocess execution. I use it now a lot, but I'm not so experienced so maybe there are some flaws in it:

import subprocessimport timedef subprocess_execute(command, time_out=60):    """executing the command with a watchdog"""    # launching the command    c = subprocess.Popen(command)    # now waiting for the command to complete    t = 0    while t < time_out and c.poll() is None:        time.sleep(1)  # (comment 1)        t += 1    # there are two possibilities for the while to have stopped:    if c.poll() is None:        # in the case the process did not complete, we kill it        c.terminate()        # and fill the return code with some error value        returncode = -1  # (comment 2)    else:                         # in the case the process completed normally        returncode = c.poll()    return returncode   

Usage:

 return = subprocess_execute(['java', '-jar', 'some.jar'])

Comments:

  1. here, the watchdog time out is in seconds; but it's easy to change to whatever needed by changing the time.sleep() value. The time_out will have to be documented accordingly;
  2. according to what is needed, here it maybe more suitable to raise some exception.

Documentation: I struggled a bit with the documentation of subprocess module to understand that subprocess.Popen is not blocking; the process is executed in parallel (maybe I do not use the correct word here, but I think it's understandable).

But as what I wrote is linear in its execution, I really have to wait for the command to complete, with a time out to avoid bugs in the command to pause the nightly execution of the script.


I guess this is a common synchronization problem in event-oriented programming with threads and processes.

If you should always have only one subprocess running, make sure the current subprocess is killed before running the next one. Otherwise the signal handler may get a reference to the last subprocess run and ignore the older.

Suppose subprocess A is running. Before the alarm signal is handled, subprocess B is launched. Just after that, your alarm signal handler attempts to kill a subprocess. As the current PID (or the current subprocess pipe object) was set to B's when launching the subprocess, B gets killed and A keeps running.

Is my guess correct?

To make your code easier to understand, I would include the part that creates a new subprocess just after the part that kills the current subprocess. That would make clear there is only one subprocess running at any time. The signal handler could do both the subprocess killing and launching, as if it was the iteration block that runs in a loop, in this case event-driven with the alarm signal every 1 second.