为什么守护程序没有join()就退出

时间:2016-03-24 00:57:16

标签: python python-2.7 python-3.x multiprocessing daemon

在下面的链接上,答案可能就在我面前,但我仍然不明白。我确定在有人向我解释之后,达尔文会打电话给我。

示例是at this link here,虽然我做了一些修改,试图尝试并帮助我理解。

以下是代码:

import multiprocessing
import time
import sys

def daemon():
    p = multiprocessing.current_process()
    print 'Starting: ', p.name, p.pid
    sys.stdout.flush()
    time.sleep(2)
    print 'Exiting: ', p.name, p.pid
    sys.stdout.flush()

def non_daemon():
    p = multiprocessing.current_process()
    print 'Starting: ', p.name, p.pid
    sys.stdout.flush()
    time.sleep(6)
    print 'Exiting: ', p.name, p.pid
    sys.stdout.flush()

if __name__ == '__main__':
    d = multiprocessing.Process(name='daemon', target=daemon)
    d.daemon = True

    n = multiprocessing.Process(name='non-daemon', target=non_daemon)
    n.daemon = False

    d.start()
    time.sleep(1)
    n.start()
#    d.join()

代码的输出是:

Starting:  daemon 6173
Starting:  non-daemon 6174
Exiting:  non-daemon 6174

如果取消注释末尾的join(),则输出为:

Starting:  daemon 6247
Starting:  non-daemon 6248
Exiting:  daemon 6247
Exiting:  non-daemon 6248

我很困惑b / c守护进程的睡眠是2秒,而非守护进程是6秒。为什么不在第一种情况下打印出“退出”消息?守护进程应该在非守护进程之前唤醒并打印消息。

该网站的解释如下:

  

输出不包含守护程序的“退出”消息   进程,因为所有的非守护进程(包括主进程)   程序)在守护程序进程从2秒唤醒之前退出   睡眠。

但我更改了它,以便守护进程应该在非守护进程之前唤醒。我在这里错过了什么?在此先感谢您的帮助。

编辑:忘了提到我正在使用python 2.7,但显然这个问题也出现在python 3.x中

1 个答案:

答案 0 :(得分:4)

这是一个有趣的追踪。这些文档有点误导,因为它们将非守护进程描述为完全等同;任何非守护进程的存在意味着进程“家庭”还活着。 But that's not how it's implemented.父进程比其他进程“更加平等”; previousIndex注册了执行以下操作的multiprocessing处理程序:

atexit

因此,当主要流程完成时,它首先 for p in active_children(): if p.daemon: info('calling terminate() for daemon %s', p.name) p._popen.terminate() for p in active_children(): info('calling join() for process %s', p.name) p.join() 所有terminate子进程,然后 daemon所有子进程等待非join个孩子并清理daemon个孩子的资源的流程。

因为它按此顺序执行清理,在非daemon daemon Process之后的一小时,主进程开始清理并强制start s {{ 1}} terminate

请注意,修复此问题可以像手动daemonProcess进程一样简单,而不仅仅join进入daemon进程(这会破坏整个过程)一个join的完全);这会阻止调用daemon处理程序,从而延迟daemon atexit个孩子的清理工作。

它可以说是一个错误(一个似乎存在于3.5.1中的错误;我责备自己),但无论是行为错误还是文档错误都是有争议的。