在塔架中的信号处理
问题描述:
我有一个塔架项目,我需要定期更新一些内存中的结构。这应该按需完成。我决定为此提出一个信号处理程序。用户发送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。
答
是的,这是可能的,但不容易使用股票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
你也可以只使用在你选择调用。
答
一个解决方法,至少对我的作品,从实际选择线路的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。
仅供参考,以下是要求在EINTR上重试的(仍然打开的)Python票证:http://bugs.python.org/issue9867 – 2012-03-22 12:15:58
@Gunnlaugur Briem很好的参考 – Wei 2012-06-14 05:53:12