2009-08-06 27 views
6

Tôi thấy điều này khi tôi nhấn Ctrl-C để thoát khỏi ứng dụng của tôiPython Đa lối ra lỗi

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 

Tôi đang sử dụng xoắn trên đầu trang của những thứ của riêng tôi,

Tôi đã đăng ký tín hiệu Ctrl-C với đoạn mã sau

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() 

và khi họ tín hiệu khác để tắt máy, nó sẽ cố gắng để nói với họ để tắt máy độc đáo qua

exit = multiprocessing.Event() 
def shutdown(self): 
    self.exit.set() 

nơi mà tất cả các quá trình của tôi là trong một số hình thức,

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

Bất kỳ ý tưởng gì lỗi này là gì? Tôi chỉ nhận được nó khi tôi có nhiều hơn một ví dụ của một chủ đề cụ thể.

Trả lời

5

Điều này liên quan đến tương tác với các cuộc gọi hệ thống, tín hiệu hệ điều hành và cách nó được xử lý trong mô-đun đa xử lý. Tôi không thực sự chắc chắn nếu nó là một lỗi hoặc một tính năng, nhưng nó trong lãnh thổ hơi khó khăn vì nó là nơi python đáp ứng các os.

Vấn đề là đa xử lý đang chặn trên waitpid cho đến khi đứa trẻ chờ đợi đã chấm dứt. Tuy nhiên, vì bạn đã cài đặt trình xử lý tín hiệu cho SIGINT và chương trình của bạn nhận được tín hiệu này, nó sẽ ngắt cuộc gọi hệ thống để thực hiện trình xử lý tín hiệu của bạn và các lần thoát khỏi waitpid cho biết rằng nó bị gián đoạn bởi tín hiệu. Cách python xử lý trường hợp này là do các ngoại lệ.

Là một khắc phục, bạn có thể gửi kèm theo phần vi phạm (s) trong một vòng lặp while và cố gắng/catch khối như thế này, hoặc là xung quanh nơi bạn chờ cho chủ đề để kết thúc, hoặc lớp con 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 

Đối mucking về với multiprocessing.forking.Popen bạn sẽ phải làm một cái gì đó như thế này:

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

wow thực sự tuyệt vời. Bất kỳ tài nguyên trực tuyến tốt nào sẽ giải thích điều gì đó đến độ sâu như vậy? –

0

tôi đã nhìn thấy điều này, nhưng nó đã đi xa khi tôi gạt xử lý tín hiệu với riêng tôi. Sử dụng reactor.run (installSignalHandlers = False) và xác định các chức năng của riêng bạn cho SIGINT, SIGTERM, v.v.

Các vấn đề liên quan