在thread.start()后运行subprocess时出现僵尸进程

2 投票
1 回答
1325 浏览
提问于 2025-04-17 11:51

我遇到了一个问题,就是在调用子进程时,应该很快就能返回的结果却被阻塞了(实际上子进程变成了无效状态,没有被清理掉)。这种情况似乎只在我使用线程的时候发生。下面的程序很好地重现了我遇到的情况。运行它时,你会看到主机名被打印出很多次,数字在范围内循环,直到它被阻塞。我怀疑一旦某个线程完成,那个无效的进程就会被清理掉,然后这个问题又会再次出现。

有没有人能告诉我发生了什么,以及我该如何在不出现这种情况的情况下同时使用线程和子进程?我在Ubuntu 11.4上使用的是Python 2.7.1+。

import os
import subprocess
import threading

class DummyThread(threading.Thread):

    def run(self):
        proc = subprocess.Popen(['sleep', '100'])
        proc.wait()

while True:
    dummy = DummyThread()
    dummy.start()
    for i in range(10):
        print i
        subprocess.check_call(['hostname'])

运行这个程序会导致一个子进程变成无效状态,并阻塞主线程:

user     28665 10543  1 22:55 pts/2        python blocker.py
user     28667 28665  0 22:55 pts/2        sleep 100
user     28679 28665  0 22:55 pts/2        sleep 100
user     28691 28665  0 22:55 pts/2        sleep 100
user     28703 28665  0 22:55 pts/2        sleep 100
user     28715 28665  0 22:55 pts/2        sleep 100
user     28727 28665  0 22:55 pts/2        sleep 100
user     28739 28665  0 22:55 pts/2        sleep 100
user     28751 28665  0 22:55 pts/2        sleep 100
user     28763 28665  0 22:55 pts/2        sleep 100
user     28775 28665  0 22:55 pts/2        sleep 100
user     28787 28665  0 22:55 pts/2        sleep 100
user     28799 28665  0 22:55 pts/2        sleep 100
user     28800 28665  0 22:55 pts/2        [hostname] <defunct>

1 个回答

2

我在ubuntu 12.04(python 2.7.3)和OS X 10.8(python 2.7.2)上复现了这个问题。

如果在调用subprocess.Popen和subprocess.check_call时设置close_fds=True,这个问题就会消失。

我不太确定这是什么意思,但这可能会帮助那些更懂的人更全面地回答这个问题。

撰写回答