2010-10-27 72 views
0

我在這裏有一個多進程的演示,我遇到了一些問題。研究了一個晚上,我無法解決原因。 任何人都可以幫助我嗎?一個python多進程錯誤

我想讓一個父進程充當生產者,當有任務到來時,父進程可以派生一些子進程來使用這些任務。父母監控孩子,如果任何一個孩子退出,並且可以由父母重新開始。

 

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

from multiprocessing import Process, Queue from Queue import Empty import sys, signal, os, random, time import traceback 

child_process = [] 
child_process_num = 4 
queue = Queue(0) 

def work(queue): 
    signal.signal(signal.SIGINT, signal.SIG_DFL) 
    signal.signal(signal.SIGTERM, signal.SIG_DFL) 
    signal.signal(signal.SIGCHLD, signal.SIG_DFL) 

    time.sleep(10) #demo sleep 

def kill_child_processes(signum, frame): 
    #terminate all children 
    pass 

def restart_child_process(signum, frame): 
    global child_process 

    for i in xrange(len(child_process)): 
     child = child_process[i] 

     try: 
      if child.is_alive(): 
       continue 
     except OSError, e: 
      pass 

     child.join() #join this process to make sure there is no zombie process 

     new_child = Process(target=work, args=(queue,)) 
     new_child.start() 
     child_process[i] = new_child #restart one new process 

     child = None 
     return 

if __name__ == '__main__': 
    reload(sys) 
    sys.setdefaultencoding("utf-8") 

    for i in xrange(child_process_num): 
     child = Process(target=work, args=(queue,)) 
     child.start() 
     child_process.append(child) 

    signal.signal(signal.SIGINT, kill_child_processes) 
    signal.signal(signal.SIGTERM, kill_child_processes) #hook the SIGTERM 
    signal.signal(signal.SIGCHLD, restart_child_process) 
    signal.signal(signal.SIGPIPE, signal.SIG_DFL) 
 

,當該程序運行時,會出現錯誤如下:

 
Error in atexit._run_exitfuncs: 
Error in sys.exitfunc: 
Traceback (most recent call last): 
    File "/usr/local/python/lib/python2.6/atexit.py", line 30, in _run_exitfuncs 
    traceback.print_exc() 
    File "/usr/local/python/lib/python2.6/traceback.py", line 227, in print_exc 
    print_exception(etype, value, tb, limit, file) 
    File "/usr/local/python/lib/python2.6/traceback.py", line 124, in print_exception 
    _print(file, 'Traceback (most recent call last):') 
    File "/usr/local/python/lib/python2.6/traceback.py", line 12, in _print 
    def _print(file, str='', terminator='\n'): 
    File "test.py", line 42, in restart_child_process 
    new_child.start() 
    File "/usr/local/python/lib/python2.6/multiprocessing/process.py", line 99, in start 
    _cleanup() 
    File "/usr/local/python/lib/python2.6/multiprocessing/process.py", line 53, in _cleanup 
    if p._popen.poll() is not None: 
    File "/usr/local/python/lib/python2.6/multiprocessing/forking.py", line 106, in poll 
    pid, sts = os.waitpid(self.pid, flag) 
OSError: [Errno 10] No child processes 
 

如果我發送信號給一個孩子:殺-SIGINT {} child_pid我將獲得:

 
[[email protected] mail]# kill -SIGINT 32545 
[[email protected] mail]# Error in atexit._run_exitfuncs: 
Traceback (most recent call last): 
    File "/usr/local/python/lib/python2.6/atexit.py", line 24, in _run_exitfuncs 
    func(*targs, **kargs) 
    File "/usr/local/python/lib/python2.6/multiprocessing/util.py", line 269, in _exit_function 
    p.join() 
    File "/usr/local/python/lib/python2.6/multiprocessing/process.py", line 119, in join 
    res = self._popen.wait(timeout) 
    File "/usr/local/python/lib/python2.6/multiprocessing/forking.py", line 117, in wait 
    return self.poll(0) 
    File "/usr/local/python/lib/python2.6/multiprocessing/forking.py", line 106, in poll 
    pid, sts = os.waitpid(self.pid, flag) 
OSError: [Errno 4] Interrupted system call Error in sys.exitfunc: 
Traceback (most recent call last): 
    File "/usr/local/python/lib/python2.6/atexit.py", line 24, in _run_exitfuncs 
    func(*targs, **kargs) 
    File "/usr/local/python/lib/python2.6/multiprocessing/util.py", line 269, in _exit_function 
    p.join() 
    File "/usr/local/python/lib/python2.6/multiprocessing/process.py", line 119, in join 
    res = self._popen.wait(timeout) 
    File "/usr/local/python/lib/python2.6/multiprocessing/forking.py", line 117, in wait 
    return self.poll(0) 
    File "/usr/local/python/lib/python2.6/multiprocessing/forking.py", line 106, in poll 
    pid, sts = os.waitpid(self.pid, flag) 
OSError: [Errno 4] Interrupted system call 
 

回答

1

主進程正在等待所有子進程在退出之前被終止,因此存在阻塞調用(即, wait4)註冊爲at_exit句柄。您發送的信號中斷阻塞呼叫,因此堆棧跟蹤。

我不清楚的是,如果發送給孩子的信號會被重定向到父進程,然後中斷wait4的調用。這與Unix進程組行爲有關。