多进程守护程序未在父出口上终止 [英] Multiprocess Daemon Not Terminating on Parent Exit

查看:96
本文介绍了多进程守护程序未在父出口上终止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Python 2.7多处理进程,该进程不会在父进程退出时退出.我设置了守护进程标志,该标志应强制其在父项死亡时退出.文档指出:

I have a Python 2.7 multiprocessing Process which will not exit on parent process exit. I've set the daemon flag which should force it to exit on parent death. The docs state that:

当进程退出时,它将尝试终止其所有守护程序子进程."

"When a process exits, it attempts to terminate all of its daemonic child processes."

p = Process(target=_serverLaunchHelper, args=args)
p.daemon = True
print p.daemon # prints True
p.start()

当我通过kill命令终止父进程时,守护程序将保持活动状态并正在运行(它将在下次运行时阻塞端口).子进程正在启动SimpleHttpServer并调用serve_forever而不执行其他任何操作.我的猜测是,文档的尝试"部分意味着阻塞服务器进程正在停止进程终止,并因此导致进程孤立.我可以让孩子将服务推送到另一个线程,并让主线程检查父进程的ID更改,但这似乎是很多代码来复制守护程序功能.

When I terminate the parent process via a kill command the daemon is left alive and running (which blocks the port on the next run). The child process is starting a SimpleHttpServer and calling serve_forever without doing anything else. My guess is that the "attempts" part of the docs means that the blocking server process is stopping process death and it's letting the process get orphaned as a result. I could have the child push the serving to another Thread and have the main thread check for parent process id changes, but this seems like a lot of code to just replicate the daemon functionality.

有人了解为什么守护程序标志无法按所述方式工作吗?在Windows8 64位和ubuntu12 32位vm上可以重复执行此操作.

Does someone have insight into why the daemon flag isn't working as described? This is repeatable on windows8 64 bit and ubuntu12 32 bit vm.

处理功能的简化版本如下:

A boiled down version of the process function is below:

def _serverLaunchHelper(port)
    httpd = SocketServer.TCPServer(("", port), Handler)
    httpd.serve_forever()

推荐答案

进程退出时,它将尝试终止其所有守护进程.

When a process exits, it attempts to terminate all of its daemonic child processes.

这里的关键词是尝试".另外,退出".

The key word here is "attempts". Also, "exits".

取决于您的平台和实现,终止守护程序子进程的唯一方法可能是明确地终止.如果父进程正常退出,则有机会明确退出,因此一切都很好.但是,如果父进程突然终止,则不会终止.

Depending on your platform and implementation, it may be that the only way to get daemonic child processes terminated is to do so explicitly. If the parent process exits normally, it gets a chance to do so explicitly, so everything is fine. But if the parent process is terminated abruptly, it doesn't.

尤其对于CPython,如果您查看,终止守护进程的方式与加入非守护进程的方式相同:在

For CPython in particular, if you look at the source, terminating daemonic processes is handled the same way as joining non-daemonic processes: by walking active_children() in an atexit function. So, your daemons will be killed if and only if your atexit handlers get to run. And, as that module's docs say:

注意:当程序被非Python处理的信号杀死,检测到Python致命内部错误或调用os._exit()时,不会调用通过此模块注册的功能.

Note: the functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when os._exit() is called.

根据您要杀死父级的方式,您也许可以通过添加信号处理程序来拦截突然终止的方法来解决此问题.但是您可能无法做到这一点-例如,在POSIX上,SIGKILL无法拦截,因此,如果您kill -9 $PARENTPID,则不能选择此选项.

Depending on how you're killing the parent, you might be able to work around this by adding a signal handler to intercept abrupt termination. But you might not—e.g., on POSIX, SIGKILL is not intercept able, so if you kill -9 $PARENTPID, this isn't an option.

另一种选择是杀死进程组,而不仅仅是父进程.例如,如果您的父母有PID 12345,则Linux上的kill -- -12345将杀死它及其所有子项(假设您没有做任何花哨的事情).

Another option is to kill the process group, instead of just the parent process. For example, if your parent has PID 12345, kill -- -12345 on linux will kill it and all of its children (assuming you haven't done anything fancy).

这篇关于多进程守护程序未在父出口上终止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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