【问题标题】:Why doesn't the daemon program exit without join()为什么没有 join() 守护程序不退出
【发布时间】:2016-03-24 00:57:15
【问题描述】:

下面的链接中的答案可能就在我面前,但我还是不明白。我相信在有人向我解释后,达尔文会打电话给我。

这个例子是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 秒。为什么它在第一种情况下不打印“退出”消息?守护进程应该在非守护进程之前唤醒并打印消息。

网站的解释是这样的:

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

但我将其更改为守护程序应该在非守护程序之前唤醒。我在这里想念什么?提前感谢您的帮助。

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

【问题讨论】:

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


    【解决方案1】:

    这是一个有趣的追踪。这些文档有些误导,因为它们描述了非守护进程,就好像它们都是等价的;任何非守护进程的存在意味着进程“家族”是活着的。 But that's not how it's implemented.父进程比其他进程“更平等”; 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()
    

    所以当主进程完成时,它首先terminates所有daemon子进程,然后joins所有子进程等待非daemonchildren 并清理来自daemonchildren 的资源。

    因为它按这个顺序执行清理,所以在你的非daemonProcessstarts 之后,主进程开始清理并强制terminates 和daemonProcess

    请注意,修复此问题可以像手动 joining 非 daemon 进程一样简单,而不仅仅是 joining daemon 进程(这完全破坏了 daemon 的全部意义);这会阻止调用 atexit 处理程序,从而延迟 terminate daemon 子级的清理。

    可以说这是一个错误(似乎存在于 3.5.1 之前的错误;我自己复制了一个),但它是行为错误还是文档错误是有争议的。

    【讨论】:

    • 我认为这是一个错误,因为它的行为不同于 threadingmultiprocessing 应该使用进程而不是线程来模拟),其中守护线程在 any 时继续运行 非守护线程保持活动状态(主线程或其他线程)。已打开bug #26633
    • 感谢您在调查此问题时做出的超越。很高兴听到我没有发疯,达尔文不会呼唤我,至少这次 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 2021-04-03
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多