如何避免Linux中的defunct python进程?

时间:2016-08-03 18:51:01

标签: python linux python-3.x

在Ubuntu 14.04上使用python3(3.4.3)我创建了一个Forker类,我在两个不同的进程中使用它来创建子进程。这是Forker类:

class Forker(object):
    def __init__(self):     
        self.active_children = []            

    def reap_children(self):                              
        while self.active_children:                        
            pid,stat = os.waitpid(0, os.WNOHANG)       
            if not pid: break
            self.active_children.remove(pid)                

    def fork(self, function, *args, **kwargs):         
        self.reap_children()

        child_pid = os.fork()
        if child_pid == 0:
            function(*args, **kwargs)
            os._exit(0)
        else:                                               
            self.active_children.append(child_pid)

        return child_pid

在我从这个类派生的两个不同的Linux进程中然后调用例如类似的东西:

self.fork(my_function, my_data)

然而,我仍然得到一些已经失效的python进程:

alexand+ 24777 24735  0 20:40 pts/29   00:00:00 [python3] <defunct>
alexand+ 24838 24733  0 20:40 pts/29   00:00:00 [python3] <defunct>

也许我可以改变一些东西来避免这些已经失效的过程?

2 个答案:

答案 0 :(得分:4)

标记为<defunct>的流程称为僵尸流程。系统将它们保持在已经不存在的状态,以允许其父级在完成运行后读取其状态。

有两种方法可以删除它们:

  • 完成后,在调用者 中等待他们。调用者可以为SIGCHLD设置一个处理程序,以警告其中一个孩子刚刚结束,或者只是不时地轮询它们
  • 只是忽略它们。如果调用者在分叉时明确忽略SIGCHLD(signal(SIGCHLD, SIG_IGN);),则会立即删除子节点(没有失效状态),但是父节点没有其他方法可以等待它们。

答案 1 :(得分:1)

离开的孩子是<defunct>,直到父母等待他们。 由于您仅在reap_children()新孩子时才在fork()中呼叫等待,所以已退出的孩子将保持<defunct>,直到下一个孩子分叉为止。要提前摆脱它们,您可以在较早时间调用reap_children()(即等待)。通常,这是通过SIGCHLD信号的处理程序完成的。