问题描述
我有一个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()
推荐答案
这里的关键词是尝试".另外,退出".
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,如果您查看源,终止守护进程的方式与加入非守护进程的方式相同:在 atexit
函数.因此,当且仅当您的atexit
处理程序开始运行时,您的守护程序才会被杀死.而且,正如该模块的文档所说:
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:
根据您要杀死父级的方式,您也许可以通过添加信号处理程序来拦截突然终止的方法来解决此问题.但是您可能无法做到这一点-例如,在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).
这篇关于多进程守护程序未在父出口上终止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!