运行超时的子流程和管道结果后挂起父流程

时间:2019-07-01 22:47:50

标签: python multithreading multiprocessing pipe deadlock

我编写了一些代码来运行脚本(通过子进程)并在一定的超时后终止子进程。我正在运行一个名为“ runtime_hang_script.sh”的脚本,该脚本仅包含“ ./runtime_hang”,该脚本运行无限循环。我还将stdout重定向到管道-我计划将其同时写入sys.stdout和文件(也就是我试图实现tee)。但是,我的代码在子进程超时后挂起。请注意,仅在运行“ sh runtime_hang_script.sh”而不是“ ./runtime_hang”时挂起。另外,当我尝试直接管道传输到文件或不从管道读取数据时,该消息也不会挂起。

我尝试了创建定时子流程的其他实现,但是我一直遇到同样的问题。我什至尝试在问题结束时发出信号-出于某种原因,信号发出的时间比预期的要早,因此这也不起作用。任何帮助,将不胜感激。预先感谢!

process = None

def run():
    global process
    timeout_secs = 5
    args = ['sh', 'runtime_hang_script.sh']
    sys.stdout.flush()

    process = subprocess.Popen(args, stdout=subprocess.PIPE, bufsize=1)

    with process.stdout:
        for line in iter(process.stdout.readline, b''):
            sys.stdout.write(line.decode('utf-8'))
        sys.stdout.flush()

    process.wait()


proc_thread = threading.Thread(target=run)
proc_thread.start()
proc_thread.join(5)

print(proc_thread.is_alive())

if proc_thread.is_alive():
    process.kill()

1 个答案:

答案 0 :(得分:0)

假设您使用的是Python 3.3或更高版本,则可以使用subprocess.communicate()方法的timeout参数来实现5秒钟的超时:

import subprocess
import sys

timeout_secs = 5
args = ['sh', 'runtime_hang_script.sh']

process = subprocess.Popen(args, stdout=subprocess.PIPE, bufsize=1)
try:
   print("Waiting for data from child process...")
   (stdoutData, stderrData) = process.communicate(None, timeout_secs)
   print("From child process:  stdoutData=[%s] stderrData=[%s]" % (stdoutData, stderrData))
except subprocess.TimeoutExpired:
   print("Oops, child process took too long!  Now it has to die")
   process.kill()

print("Waiting for child process to exit...")
process.wait()
print("Child process exited.")

请注意,使用此方法无需生成子线程,因为超时可以直接在主线程中起作用。