2011-04-12 39 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。