Asi*_*man 6 python daemon multiprocessing
在python守护进程(使用python-daemon)中使用多处理模块时,我收到以下错误:
Traceback (most recent call last):
File "/usr/local/lib/python2.6/atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "/usr/local/lib/python2.6/multiprocessing/util.py", line 262, in _exit_function
for p in active_children():
File "/usr/local/lib/python2.6/multiprocessing/process.py", line 43, in active_children
_cleanup()
File "/usr/local/lib/python2.6/multiprocessing/process.py", line 53, in _cleanup
if p._popen.poll() is not None:
File "/usr/local/lib/python2.6/multiprocessing/forking.py", line 106, in poll
pid, sts = os.waitpid(self.pid, flag)
OSError: [Errno 10] No child processes
守护进程(父进程)生成许多进程(子进程),然后定期轮询进程以查看它们是否已完成.如果父进程检测到其中一个进程已完成,则会尝试重新启动该进程.正是在这一点上提出了上述异常.似乎一旦其中一个进程完成,涉及多处理模块的任何操作都将生成此异常.如果我在非守护程序python脚本中运行相同的代码,它将执行,没有任何错误.
编辑:
示例脚本
from daemon import runner
class DaemonApp(object):
def __init__(self, pidfile_path, run):
self.pidfile_path = pidfile_path
self.run = run
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
def run():
import multiprocessing as processing
import time
import os
import sys
import signal
def func():
print 'pid: ', os.getpid()
for i in range(5):
print i
time.sleep(1)
process = processing.Process(target=func)
process.start()
while True:
print 'checking process'
if not process.is_alive():
print 'process dead'
process = processing.Process(target=func)
process.start()
time.sleep(1)
# uncomment to run as daemon
app = DaemonApp('/root/bugtest.pid', run)
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
#uncomment to run as regular script
#run()
Run Code Online (Sandbox Code Playgroud)
您的问题是守护程序和多处理模块之间的冲突,特别是在处理SIGCLD(子进程终止)信号时.守护进程在启动时将SIGCLD设置为SIG_IGN,至少在Linux上,会导致终止的子进程立即被收获(而不是在父进程调用wait()之前成为僵尸).但是多处理的is_alive测试调用wait()来查看进程是否处于活动状态,如果进程已被收集,则进程失败.
最简单的解决方案就是将SIGCLD设置回SIG_DFL(默认行为 - 忽略信号并让父进程wait()用于已终止的子进程):
def run():
# ...
signal.signal(signal.SIGCLD, signal.SIG_DFL)
process = processing.Process(target=func)
process.start()
while True:
# ...
Run Code Online (Sandbox Code Playgroud)
忽略SIGCLD还会导致模块出现问题subprocess,因为该模块中存在错误(问题 1731717,截至 2011 年 9 月 21 日仍处于开放状态)。
此行为已在该库的1.4.8 版本python-daemon中得到解决;它现在省略了默认的摆弄SIGCLD,因此不再与其他标准库模块进行这种令人不快的交互。
| 归档时间: |
|
| 查看次数: |
4325 次 |
| 最近记录: |