多处理产生不复存在的进程

Ke *_* Lu 4 python multiprocessing python-2.7

我使用 Tornado 作为 Web 服务器,用户可以通过前端页面提交任务,审核后他们可以启动提交的任务。在这种情况下,我想启动一个异步子进程来处理任务,因此我在请求处理程序中编写了以下代码:

def task_handler():
    // handle task here

def start_a_process_for_task():
    p = multiprocessing.Process(target=task_handler,args=())
    p.start()
    return 0
Run Code Online (Sandbox Code Playgroud)

我不关心子流程,只是为它启动一个流程并返回前端页面并告诉用户任务已启动。任务本身将在后台运行,并将其状态或结果记录到数据库中,以便用户稍后可以在网页上查看。所以在这里我不想使用阻塞的 p.join(),但是在任务完成后没有 p.join(),子进程成为一个不复存在的进程,因为 Tornado 作为守护进程运行并且永不退出,不复存在过程永远不会消失。

谁知道怎么解决这个问题,谢谢。

she*_*ron 7

避免失效孩子的正确方法是让父母优雅地清理和关闭退出孩子的所有资源。这通常由 完成join(),但如果您想避免这种情况,另一种方法可能是SIGCHLD为父级上的信号设置全局处理程序。

SIGCHLD将在子Process.join()进程退出时发出,并且在处理程序函数中,如果您仍然可以访问进程对象,您应该调用它,或者甚至使用os.wait()“等待”任何子进程终止并正确获取它。此处的等待时间应为 0,因为您肯定知道子进程刚刚退出。您还可以获取进程的退出代码/终止信号,因此它也是处理/记录子进程崩溃的有用方法。

这是执行此操作的快速示例:

from __future__ import print_function

import os
import signal
import time
from multiprocessing import Process


def child_exited(sig, frame):
    pid, exitcode = os.wait()
    print("Child process {pid} exited with code {exitcode}".format(
        pid=pid, exitcode=exitcode
    ))


def worker():
    time.sleep(5)
    print("Process {pid} has completed it's work".format(pid=os.getpid()))


def parent():
    children = []

    # Comment out the following line to see zombie children
    signal.signal(signal.SIGCHLD, child_exited)

    for i in range(5):
        c = Process(target=worker)
        c.start()
        print("Parent forked out worker process {pid}".format(pid=c.pid))
        children.append(c)
        time.sleep(1)

    print("Forked out {c} workers, hit Ctrl+C to end...".format(c=len(children)))
    while True:
        time.sleep(5)


if __name__ == '__main__':
    parent()
Run Code Online (Sandbox Code Playgroud)

一个警告是,我不确定这个过程是否适用于非 Unix 操作系统。它应该适用于 Linux、Mac 和其他 Unix。