<H3> Tl;DR<EH3>
<p>在读取Python中的管道时,我是否应该处理EINTR“系统调用中断”错误,如果是,如何测试这些代码?在</p>
<h3>说明</h3>
<p>在下面的回溯中,<code>self._dataq</code>是<code>multiprocessing.Queue</code>(技术上,我使用的是<code>billiard</code>库,但我认为它们基本上是相同的代码)。Python子进程偶尔会写入队列的另一端。我想发生的是,一个系统调用正在读取为队列提供数据的管道,然后一个信号到达了——可能是来自第二个Ctrl+C事件的SIGINT(第一个SIGINT发生在日志输出的第二行,用户的<code>^C</code>,我的信号处理程序捕捉到了这个SIGINT,您可以在日志中的警告消息中看到)。在</p>
<pre><code>[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
</code></pre>
<p>上面回溯中的语句<code>result = self._dataq.get(timeout=0.1)</code>位于如下所示的循环中间。循环的主要目的是,当<code>self.timedout()</code>开始返回<code>True</code>时,我可以放弃从<code>self._dataq</code>读取数据。在</p>
^{pr2}$
<h3>问题</h3>
<p>如果我关于^{<cd9>发生的原因的理论是正确的,那么上面的<code>try</code>…<code>except</code>块应该捕捉并忽略<code>IOError</code>是由中断的系统调用引起的。如果是一个信号导致了EINTR错误,那么仅仅返回Python运行<code>except IOError:</code>语句就可以运行Python级别的信号处理程序。在</p>
<p>对吗?如果是这样,有没有可能在我的代码中测试这个更改?对于我来说,如何编写一个不包含严重竞争条件的单元测试并不明显。在</p>