我有一个Python 2.7多处理过程,它不会在父进程退出时退出。我已经设置了守护进程标志,它应该强制它在父母死亡时退出。文档指出:
“当一个进程退出时,它会尝试终止所有守护进程的子进程。”
p = Process(target=_serverLaunchHelper, args=args)
p.daemon = True
print p.daemon # prints True
p.start()
当我通过kill命令终止父进程时,守护进程处于活动状态并且正在运行(在下次运行时阻塞该端口)。子进程正在启动SimpleHttpServer并调用 serve_forever
没有做任何其他事情。我的猜测是文档中的“尝试”部分意味着阻塞服务器进程正在停止进程死亡,并且它会让进程因此而变为孤立状态。我可以让孩子将服务推送到另一个线程并让主线程检查父进程id更改,但这似乎只是复制守护进程功能的很多代码。
是否有人能够深入了解守护程序标志无法正常工作的原因?这在windows8 64位和ubuntu12 32位vm上是可重复的。
流程函数的简化版本如下:
def _serverLaunchHelper(port)
httpd = SocketServer.TCPServer(("", port), Handler)
httpd.serve_forever()
当进程退出时,它会尝试终止其所有守护进程子进程。
这里的关键词是“尝试”。另外,“退出”。
根据您的平台和实现,可能是终止守护进程子进程的唯一方法是明确地这样做。如果父进程正常退出,它有机会明确地这样做,所以一切都很好。但如果父进程突然终止,则不会。
特别是对于CPython,如果你看一下 来源,终止守护进程的处理方式与加入非守护进程的方式相同:通过遍历 active_children()
在一个 atexit
功能。所以,你的守护进程将被杀死,当且仅当你的守护进程被杀死 atexit
处理程序可以运行。并且,正如该模块的文档所说:
注意:当程序被Python未处理的信号杀死,检测到Python致命内部错误时,或者何时被调用时,不会调用通过此模块注册的函数 os._exit()
叫做。
根据您如何杀死父级,您可以通过添加信号处理程序来拦截突然终止来解决此问题。但你可能不会 - 例如,在POSIX上, SIGKILL
不能拦截,所以如果你 kill -9 $PARENTPID
,这不是一个选择。
另一种选择是杀死进程组,而不仅仅是父进程。例如,如果您的父母有PID 12345, kill -- -12345
在Linux上将杀死它和它的所有孩子(假设你没有做任何花哨的事情)。
当进程退出时,它会尝试终止其所有守护进程子进程。
这里的关键词是“尝试”。另外,“退出”。
根据您的平台和实现,可能是终止守护进程子进程的唯一方法是明确地这样做。如果父进程正常退出,它有机会明确地这样做,所以一切都很好。但如果父进程突然终止,则不会。
特别是对于CPython,如果你看一下 来源,终止守护进程的处理方式与加入非守护进程的方式相同:通过遍历 active_children()
在一个 atexit
功能。所以,你的守护进程将被杀死,当且仅当你的守护进程被杀死 atexit
处理程序可以运行。并且,正如该模块的文档所说:
注意:当程序被Python未处理的信号杀死,检测到Python致命内部错误时,或者何时被调用时,不会调用通过此模块注册的函数 os._exit()
叫做。
根据您如何杀死父级,您可以通过添加信号处理程序来拦截突然终止来解决此问题。但你可能不会 - 例如,在POSIX上, SIGKILL
不能拦截,所以如果你 kill -9 $PARENTPID
,这不是一个选择。
另一种选择是杀死进程组,而不仅仅是父进程。例如,如果您的父母有PID 12345, kill -- -12345
在Linux上将杀死它和它的所有孩子(假设你没有做任何花哨的事情)。