【问题标题】:How to use Popen to run backgroud process and avoid zombie?如何使用 Popen 运行后台进程并避免僵尸?
【发布时间】:2011-09-20 12:13:11
【问题描述】:

我有一个侦听器服务器为每个客户端处理程序运行新线程。每个处理程序可以使用:

proc = subprocess.Popen(argv, executable = "./Main.py", stdout = _stdout, stderr = subprocess.STDOUT, close_fds=False)

在处理线程结束后在后台运行新进程。

后台进程结束后,一直保持在Z状态。是否可以要求 subprocess.Popen() 处理 SIG_CHILD 以避免这个僵尸?

我不想使用 proc.wait() 读取进程状态,因为为此我必须保存所有正在运行的后台进程的列表...

UPD

我需要在后台运行一些进程以避免僵尸,并使用 .communicate() 运行一些进程以从这些进程中读取数据。在这种情况下,使用 koblas 的信号技巧会出现错误:

File "./PyZWServer.py", line 115, in IsRunning
  return (subprocess.Popen(["pgrep", "-c", "-x", name], stdout=subprocess.PIPE).communicate()[0] == "0")
File "/usr/lib/python2.6/subprocess.py", line 698, in communicate
  self.wait()
File "/usr/lib/python2.6/subprocess.py", line 1170, in wait
  pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
File "/usr/lib/python2.6/subprocess.py", line 465, in _eintr_retry_call
   return func(*args)
OSError: [Errno 10] No child processes
Error happened during handling of client

【问题讨论】:

  • 也许我无意中忽略了一些东西,但我不明白最后一句话的逻辑。为什么“我必须保存所有正在运行的后台进程的列表”导致“我不想使用 proc.wait() 读取进程状态”?
  • 我已经编辑了这句话。如果我想读取状态,我必须保存这个列表,但我不需要状态并且不想保存这个列表只是为了读取状态......
  • 哦,好的。我把它读作“我已经在保存状态,所以我不想使用 proc.wait()”我现在明白了。

标签: python process subprocess zombie-process


【解决方案1】:

如果您为 SIGCHLD 添加信号处理程序,您将让内核处理等待/回收部分。

具体是一行:

signal.signal(signal.SIGCHLD, signal.SIG_IGN)

会照顾你的僵尸。

【讨论】:

  • 谢谢,这可行,但适用于所有进程。以及如何仅对某些进程执行相同的操作?我需要在后台运行一些进程以避免僵尸,并使用 .communicate() 运行一些进程以从这些进程中读取数据。在这种情况下,我得到一个错误。查看问题的更新。
  • 在解决这个问题时,挑战在于communicate() 假设了一堆行为。如果您包装自己的 Popen 并构造一个信号处理程序,则由于传递了 SIGCHLD 信号(它不会重试),因此 communcicate() 可能会因中断的读取调用而中止。因此,“正确”的解决方法是让您拥有自己的 Popen 版本来满足您的需求。另一种选择是对于您不想僵尸的进程,您需要将它们双重包装,以便您可以收获父进程让一个子孩子自己跑。
  • 出色的答案!多年来一直在努力照顾孩子,而不使用直接引用 Popen 实例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2019-12-31
相关资源
最近更新 更多