2010-10-27 22 views
0

J'ai une démo multitraitement ici, et j'ai rencontré quelques problèmes avec elle. Recherché pour une nuit, je ne peux pas résoudre la raison. Tout le monde peut m'aider?Une erreur python multiprocess

Je souhaite qu'un processus parent agisse en tant que producteur. Lorsque des tâches sont exécutées, le parent peut utiliser certains enfants pour consommer ces tâches. Le parent surveille l'enfant, s'il existe une exception, il peut être redémarré par le parent.

 

#!/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) 
 

Lorsque ce programme fonctionne, il y aura des erreurs comme ci-dessous:

 
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 
 

Si j'envoie un signal à un enfant: kill -SIGINT {} child_pid J'obtiendrai:

 
[[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 
 

Répondre

1

La procédure principale attend que tous les processus enfants soient terminés avant de quitter elle-même, de sorte qu'il y a un appel de blocage (c.-à-d. wait4) enregistré en tant que poignées at_exit. Le signal que vous avez envoyé interrompt ce blocage et appelle ainsi la trace de la pile. La chose dont je ne suis pas certain est que si le signal envoyé à l'enfant serait redirigé vers le processus parent, qui a alors interrompu cet appel wait4. C'est quelque chose lié aux comportements de groupe de processus Unix.