Python的select在Linux中处理EINTR的解决方法有哪些?

2 投票
2 回答
1019 浏览
提问于 2025-04-17 06:23

在我最近的一个项目中,我碰巧在同一个进程里(这是一个多线程的Python程序)有:

  • 一个Boost::Python模块,它连接了一个库,这个库又链接了AVT PvAPI SDK,简单来说就是一个用来从相机获取图像帧的驱动程序。这个库(PvApi SDK)内部每隔几毫秒就会产生一个SIGALRM信号。

  • 另一个普通的Python模块,目的是使用pyserial进行一些串行输入输出操作。这个模块又使用了Python的一个包装器select.select来实现POSIX的select。结果发现,每当另一个模块产生信号时,这个调用就会被打断(errno == EINTR)。

  • 在Python的time.sleep调用上也能观察到同样的问题,实际上它内部使用的是POSIX的sleep

这些问题在Windows上显然不存在,因为在Windows中,sleep和select不会被任何信号打断(根据文档)。而在C/C++中,这些问题也不是很麻烦,因为如果调用被打断,你可以(而且应该)重新启动这些调用。

然而,由于Python的实现(源代码/Modules/selectmodule.c)没有处理这种情况(EINTR),我是否被迫要自己实现一个C/C++的串行驱动和睡眠函数来在Python中使用?或者为了这个项目放弃Python?因为Python让编程变得简单,我很想知道是否有人遇到过类似的问题,并找到了一些好的解决方法或简单的修复。目前我没有能力自己解决Python模块的必要修复。或者我可能错过了其他的选择?

有什么想法吗?

2 个回答

0

试试使用 signal.siginterrupt 来让 SIGALRM 信号自动重新启动系统调用。或者你可以使用 signal.signal(signal.SIGALRM, signal.SIG_IGN) 来忽略这个报警信号,前提是你并没有用它做其他事情。

0

与此同时,发布了一个PEP来解决这个问题(PEP 475)。

看起来,从2015年的Python 3.5版本开始,这个问题就被修复了。

撰写回答