为什么没有join()的守护程序无法退出 [英] Why doesn't the daemon program exit without join()

查看:135
本文介绍了为什么没有join()的守护程序无法退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The answer might be right in front of me on the link below but I still don't understand. I'm sure after someone explains this to me, Darwin will be making a call to me.

示例是此处的链接,尽管我已经进行了一些更改以尝试进行实验并帮助我理解.

The example is at this link here, although I've made some changes to try to experiment and help my understanding.

代码如下:

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()未注释,则输出为:

If the join() at the end is uncommented, then the output is:

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

我很困惑b/c守护程序的睡眠时间是2秒,而非守护程序的睡眠时间是6秒.为什么在第一种情况下它不打印出退出"消息?守护程序应该在非守护程序之前醒来并打印消息.

I'm confused b/c the sleep of the daemon is 2 sec, whereas the non-daemon is 6 sec. Why doesn't it print out the "Exiting" message in the first case? The daemon should have woken up before the non-daemon and printed the message.

该网站的解释是这样的:

The explanation from the site is as such:

输出不包含守护程序的"Exiting"消息 进程,因为所有非守护进程(包括主进程) 程序)在守护进程从其2秒唤醒之前退出 睡觉.

The output does not include the "Exiting" message from the daemon process, since all of the non-daemon processes (including the main program) exit before the daemon process wakes up from its 2 second sleep.

但是我对其进行了更改,以使守护程序应该在非守护程序之前唤醒.我在这里想念什么?预先感谢您的帮助.

but I changed it such that the daemon should have woken up before the non-daemon does. What am I missing here? Thanks in advance for your help.

忘了提及我使用的是python 2.7,但显然此问题也在python 3.x中

Forgot to mention I'm using python 2.7 but apparently this problem is also in python 3.x

推荐答案

这很有趣.这些文档在某种程度上具有误导性,因为它们将非守护进程描述为等同于所有进程.任何非守护进程的存在都意味着进程家庭"还活着. 但这并不是它的实现方式.过程比其他过程更平等"; multiprocessing注册一个执行以下操作的atexit处理程序:

This was a fun one to track down. The docs are somewhat misleading, in that they describe the non-daemon processes as if they are all equivalent; the existence of any non-daemon process means the process "family" is alive. But that's not how it's implemented. The parent process is "more equal" than others; multiprocessing registers an atexit handler that does the following:

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个孩子的资源.

So when the main process finishes, it first terminates all daemon child processes, then joins all child processes to wait on non-daemon children and clean up resources from daemon children.

因为它按此顺序执行清理,所以在非daemon Process start s之后的一瞬间,主进程开始清理并强制terminate s daemon Process.

Because it performs cleanup in this order, a moment after your non-daemon Process starts, the main process begins cleanup and forcibly terminates the daemon Process.

请注意,解决此问题的方法很简单,例如手动join进行非daemon进程,而不仅仅是join进行daemon进程(这完全破坏了daemon的要点);阻止atexit处理程序被调用,从而延迟了terminate daemon子级的清理.

Note that fixing this can be as simple as joining the non-daemon process manually, not just joining the daemon process (which defeats the whole point of a daemon completely); that prevents the atexit handler from being called, delaying the cleanup that would terminate the daemon child.

这可以说是一个错误(似乎在3.5.1之前一直存在;我对此表示谴责),但是无论是行为错误还是文档错误,都是有争议的.

It's arguably a bug (one that seems to exist up through 3.5.1; I reproed myself), but whether it's a behavior bug or a docs bug is arguable.

这篇关于为什么没有join()的守护程序无法退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆