def run_command_with_timeout(cmd, timeout_sec): """Execute `cmd` in a subprocess and enforce timeout `timeout_sec` seconds. Return subprocess exit code on natural completion of the subprocess. Raise an exception if timeout expires before subprocess completes.""" proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, preexec_fn=os.setsid) print proc.pid def kill_proc(): print 'kill proc timer!' timer.expired = True os.killpg(proc.pid, signal.SIGTERM) # proc.terminate() timer = Timer(timeout_sec, kill_proc) timer.expired = False timer.start() stdout_value, stderr_value = proc.communicate() if timer.expired: # Process killed by timer - raise exception return 'timeout', proc.returncode, stdout_value, stderr_value # Process completed naturally - cancel timer and return exit code timer.cancel() return 'done', proc.returncode, stdout_value, stderr_value