Popen在Python 2.7中不返回
我正在用Python开发一个进程调度器。其思想是从主函数创建几个线程,并在每个线程中启动一个外部进程。外部进程应该继续运行,直到它完成或者主线程决定停止它(通过发送kill信号),因为进程的CPU时间限制被超过 问题是,Popen在Python 2.7中不返回,python,multithreading,python-2.7,process,Python,Multithreading,Python 2.7,Process,我正在用Python开发一个进程调度器。其思想是从主函数创建几个线程,并在每个线程中启动一个外部进程。外部进程应该继续运行,直到它完成或者主线程决定停止它(通过发送kill信号),因为进程的CPU时间限制被超过 问题是,Popen调用有时会阻塞并无法返回。这段代码在我的系统(Ubuntu 14.04.3 LTS)上以大约50%的概率再现了这个问题: 输出表明只有3个Popen()调用返回: Run subprocess: /bin/cat Run subprocess: /bin/cat Run
Popen
调用有时会阻塞并无法返回。这段代码在我的系统(Ubuntu 14.04.3 LTS)上以大约50%的概率再现了这个问题:
输出表明只有3个Popen()
调用返回:
Run subprocess: /bin/cat
Run subprocess: /bin/cat
Run subprocess: /bin/cat
Run subprocess: /bin/cat
started a process
started a process
started a process
all threads started
但是,运行ps
表明所有四个进程实际上都已启动
使用Python3.4时不会出现这个问题,但我希望保持Python2.7的兼容性
编辑:如果我在启动每个后续线程之前添加一些延迟,问题也会消失
编辑2:我做了一些调查,阻塞是由subprocess.py
模块中的第1308行引起的,该行试图从父进程中的管道执行一些读取:
data = _eintr_retry_call(os.read, errpipe_read, 1048576)
Python2.7的
子进程
模块中存在一些bug,当从多个线程调用Popen
构造函数时,这些bug可能导致死锁。它们在Python的更高版本3.2+IIRC中得到了修复
您可能会发现,使用Python 3.2/3.3的子流程模块的子流程32
后端口可以解决您的问题
*我无法找到实际错误报告的链接,但最近在处理类似问题时遇到了它。我可以重现您描述的行为。但是,您的示例中存在一些问题:首先,在进入while循环之前添加一个输出,然后在Popen()
之后立即添加输出。这不会改变任何事情,但会让事情变得更清楚。然后,就可以访问Process.counter
,这可能会导致竞态条件,所以请删除它,但它也不会改变问题。然后,有一件事肯定是错的,那就是finally
子句中的return-retcode
,因为finally
子句即使在return
时也会执行,但仍然没有更改。有趣的问题@UlrichEckhardt我根据您的建议更新了代码,并在最后添加了更多的信息。有趣的是,我认为我有相同的问题,因为我使用多线程与调制解调器通信,有时它只是挂起:
data = _eintr_retry_call(os.read, errpipe_read, 1048576)