2011-04-12 38 views
4

我有一個塔架項目,我需要定期更新一些內存中的結構。這應該按需完成。我決定爲此提出一個信號處理程序。用戶發送SIGUSR1到主塔線程並由項目處理。在塔架中的信號處理

這個工程除了處理信號時,服務器崩潰,以下異常後:

File "/usr/lib/python2.6/SocketServer.py", line 264, in handle_request 
    fd_sets = select.select([self], [], [], timeout) 
select.error: (4, 'Interrupted system call') 

是否有可能解決這一問題?

TIA。

回答

5

是的,這是可能的,但不容易使用股票Python庫。這是由於Python將所有操作系統錯誤轉換爲異常。但是,EINTR應該真正導致重試使用的系統調用。每當你開始在Python中使用信號時,你會偶爾看到這個錯誤。

我有code that fixes this(SafeSocket),通過分叉Python模塊並添加該功能。但是在任何使用系統調用的地方都需要添加它。所以這是可能的,但並不容易。但是你可以使用我的開源代碼,它可以爲你節省多年的工作。 ;-)

基本的模式是這樣的(實現爲一個系統調用裝飾):

# decorator to make system call methods safe from EINTR 
def systemcall(meth): 
    # have to import this way to avoid a circular import 
    from _socket import error as SocketError 
    def systemcallmeth(*args, **kwargs): 
     while 1: 
      try: 
        rv = meth(*args, **kwargs) 
      except EnvironmentError as why: 
       if why.args and why.args[0] == EINTR: 
        continue 
       else: 
        raise 
      except SocketError as why: 
       if why.args and why.args[0] == EINTR: 
        continue 
       else: 
        raise 
      else: 
       break 
     return rv 
    return systemcallmeth 

你也可以只使用在你選擇調用。

+1

僅供參考,以下是要求在EINTR上重試的(仍然打開的)Python票證:http://bugs.python.org/issue9867 – 2012-03-22 12:15:58

+0

@Gunnlaugur Briem很好的參考 – Wei 2012-06-14 05:53:12

2

一個解決方法,至少對我的作品,從實際選擇線路的12 year old python-dev list post

while True: 
     try: 
      readable, writable, exceptional = select.select(inputs, outputs, inputs, timeout) 
     except select.error, v: 
      if v[0] != errno.EINTR: raise 
     else: break 

的細節並不重要......你的「的fd_sets = select.select([個體經營],[ ],[],超時)「行應該工作完全一樣。

重要的一點是檢查EINTR,如果被捕獲,則重試/循環。 哦,不要忘記導入errno。