2009-08-06 25 views
6

私はこれを見て、私は私のアプリPythonのマルチプロセッシング出口エラー

Error in atexit._run_exitfuncs: 
Traceback (most recent call last): 
    File "/usr/lib/python2.6/atexit.py", line 24, in _run_exitfuncs 
    func(*targs, **kargs) 
    File "/usr/lib/python2.6/multiprocessing/util.py", line 269, in _exit_function 
    p.join() 
    File "/usr/lib/python2.6/multiprocessing/process.py", line 119, in join 
    res = self._popen.wait(timeout) 
    File "/usr/lib/python2.6/multiprocessing/forking.py", line 117, in wait 
    return self.poll(0) 
    File "/usr/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/lib/python2.6/atexit.py", line 24, in _run_exitfuncs 
    func(*targs, **kargs) 
    File "/usr/lib/python2.6/multiprocessing/util.py", line 269, in _exit_function 
    p.join() 
    File "/usr/lib/python2.6/multiprocessing/process.py", line 119, in join 
    res = self._popen.wait(timeout) 
    File "/usr/lib/python2.6/multiprocessing/forking.py", line 117, in wait 
    return self.poll(0) 
    File "/usr/lib/python2.6/multiprocessing/forking.py", line 106, in poll 
    pid, sts = os.waitpid(self.pid, flag) 
OSError: [Errno 4] Interrupted system call 

を終了するにはCtrl-Cを押したときに、私は私自身のものの上にツイストを使用しています、

ています私は、信号はCtrl-Cを登録次のコード

def sigHandler(self, arg1, arg2): 
     if not self.backuped: 
      self.stopAll() 
     else: 
      out('central', 'backuped ALREADY, now FORCE exiting') 
      exit() 


    def stopAll(self): 
     self.parserM.shutdown() 
     for each in self.crawlM: 
      each.shutdown() 
     self.backup() 
     reactor.stop() 

、彼らがシャットダウンするように他の人に合図するとき、それはうまく

てシャットダウンにそれらを教えしようとすると私のすべてのプロセスが何らかの形である
exit = multiprocessing.Event() 
def shutdown(self): 
    self.exit.set() 

、このエラーが何であるか

def run(self): 
    while not self.exit.is_set(): 
     do something 
    out('crawler', 'crawler exited sucessfully') 

任意のアイデア?私は、特定のスレッドのインスタンスが複数ある場合にのみ取得します。

答えて

5

これは、OSのシステムコール、信号、およびマルチプロセッシングモジュールでの処理方法との相互作用に関連しています。私はそれがバグか機能かどうかは分かりませんが、PythonがOSと出会う場所はやや難しいです。

問題は、待機中の子が終了するまで、waitpidでマルチプロセッシングがブロックされていることです。しかし、SIGINT用のシグナルハンドラをインストールし、プログラムがこのシグナルを受け取ると、シグナルハンドラを実行するシステムコールを中断し、waitpidはシグナルによって中断されたことを示して終了します。 Pythonがこのケースを処理する方法は例外です。

回避策として

、あなたはwhileループで問題のあるセクション(複数可)を同封し、このような/ catchブロックを試し、どちらかあなたが待っているの周りにスレッドが終了するのを、またはサブクラスmultiprocessing.Popenことができます。

import errno 
from multiprocessing import Process 

p = Process(target=func, args=stuff) 
p.start() 
notintr = False 
while not notintr: 
    try: 
    p.join() # "Offending code" 
    notintr = True 
    except OSError, ose: 
    if ose.errno != errno.EINTR: 
     raise ose 
あなたはこのような何かをする必要があると思いますmultiprocessing.forking.Popenで約いじくるために

import errno 
from multiprocessing import Process 
from multiprocessing.forking import Popen 
import os 

# see /path/to/python/libs/multiprocessing/forking.py 
class MyPopen(Popen): 
    def poll(self, flag=os.WNOHANG): # from forking.py 
    if self.returncode is None: # from forking.py 
     notintr = False 
     while not notintr: 
     try: 
      pid, sts = os.waitpid(self.pid, flag) # from forking.py 
      notintr = True 
     except OSError, ose: 
      if ose.errno != errno.EINTR: 
      raise ose 
     # Rest of Popen.poll from forking.py goes here 

p = Process(target=func args=stuff) 
p._Popen = p 
p.start() 
p.join() 
+0

本当に素晴らしいです。このような深みに何かを説明する良いリソースはオンラインですか? –

0

私はこれを見ていたが、私は自分自身でシグナルハンドラをオーバーライドするとき、それは去っていきました。 reactor.run(installSignalHandlers = False)を使用し、SIGINT、SIGTERMなどの独自の関数を定義してください。

関連する問題