【问题标题】:subprocess becomes defunct, `communicate()` hangs子进程失效,`communicate()` 挂起
【发布时间】:2018-11-11 18:31:49
【问题描述】:

在 Ubuntu 14.04 上的 python 2.7 中,我启动了一个这样的进程:

bag_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for i in range(5):
    print "Countdown: {}".format(5 - i - 1)
    time.sleep(1)
print "Sending SIGINT to PID {}".format(bag_process.pid)
bag_process.send_signal(signal.SIGINT)
(bag_out, bag_err) = bag_process.communicate()

程序挂在communicate() 行。当我打开另一个终端时,我运行ps -ef | grep ### 来查找子进程的pid,我看到它是<defunct>

为什么子程序失效,而父程序挂在communicate()?如果子进程在收到SIGINT 后真正退出,我怎样才能让父程序可靠地处理它而不挂起?

【问题讨论】:

  • 它已经失效了,因为它已经退出了,但是父进程还没有读出退出代码,见en.wikipedia.org/wiki/Zombie_process。也许 SIGINT 对子进程所附加的管道做了一些事情,比如发出重新打开文件句柄的信号?如果没有流程本身,这不是我们可以更具体的。
  • 您的死程序是否有可能启动仍然活着的子程序(它们从未关闭它们继承的 stdout 和 stderr),或者通过套接字将其 stdout 或 stderr FD 传递给仍然打开它们的其他程序?这两种情况都可以为communicate() 无法完成和返回提供可靠的解释。
  • @MartijnPieters 谢谢,但我相信communicate() 方法使用wait() 来获取退出状态,即使communicate() 本身不返回退出状态。 github.com/python/cpython/blob/2.7/Lib/subprocess.py#L452
  • @CharlesDuffy 好主意,但没有骰子...我为已失效的 pid 进行了搜索,它没有被列为任何其他 PID 的 PPID。
  • @EdwardNedHarvey:是的,但它永远不会到达那里,因为管道被某处阻塞。

标签: python python-2.7 subprocess defunct


【解决方案1】:

问题是:不要像这样杀死进程:

bag_process.send_signal(signal.SIGINT)

相反,像这样终止进程及其所有子进程:

parent = psutil.Process(bag_process.pid)
for child in parent.get_children(recursive=True):
    child.send_signal(signal.SIGINT)
bag_process.send_signal(signal.SIGINT)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 2012-09-07
    • 2016-09-23
    • 2015-07-07
    • 1970-01-01
    相关资源
    最近更新 更多