在读取Python中的管道时,我是否应该处理EINTR“系统调用中断”错误,如果是,如何测试这些代码?在
在下面的回溯中,self._dataq
是multiprocessing.Queue
(技术上,我使用的是billiard
库,但我认为它们基本上是相同的代码)。Python子进程偶尔会写入队列的另一端。我想发生的是,一个系统调用正在读取为队列提供数据的管道,然后一个信号到达了——可能是来自第二个Ctrl+C事件的SIGINT(第一个SIGINT发生在日志输出的第二行,用户的^C
,我的信号处理程序捕捉到了这个SIGINT,您可以在日志中的警告消息中看到)。在
[INFO 2014-03-05 14:16:06,000] Doing some work, la-dee-da
^C[WARNING 2014-03-05 14:16:07,344] Commencing shutdown. (Signal SIGINT, process 2469.). Press Ctrl+C again to exit immediately.
[DEBUG 2014-03-05 14:16:07,347] Terminating subprocess
Traceback (most recent call last):
[... a bunch of stuff omitted]
File "mycode.py", line 97, in __next__
result = self._dataq.get(timeout=0.1)
File "/usr/local/lib/python2.7/site-packages/billiard/queues.py", line 103, in get
if timeout < 0 or not self._poll(timeout):
IOError: [Errno 4] Interrupted system call
上面回溯中的语句result = self._dataq.get(timeout=0.1)
位于如下所示的循环中间。循环的主要目的是,当self.timedout()
开始返回True
时,我可以放弃从self._dataq
读取数据。在
如果我关于^{try
…except
块应该捕捉并忽略IOError
是由中断的系统调用引起的。如果是一个信号导致了EINTR错误,那么仅仅返回Python运行except IOError:
语句就可以运行Python级别的信号处理程序。在
对吗?如果是这样,有没有可能在我的代码中测试这个更改?对于我来说,如何编写一个不包含严重竞争条件的单元测试并不明显。在
我将称之为Python中的bug。我找不到允许^{} 在} ),而且它不会直接映射到任何提供这种行为的低级C函数。在C级别上有处理所有
EINTR
上引发IOError
的任何文档(尽管在其他I/O问题上引发是有意义的,这就是为什么您应该在忽略引发的异常之前检查errno属性;请参见^{EINTR
的some discussion,但这并没有使它成为3.4(我怀疑它是否会成为2.x版本),所以这可能仍然是一个值得报道的游戏。在python3.5通过将处理
EINTR
的责任放在Python运行时而不是应用程序代码上来解决这个问题。请参见PEP 475和{a2}。在相关问题 更多 >
编程相关推荐