我正在尝试实现一个托盘图标,它可以让我控制一个进程(jackd)。最为显着地
- 我想读取进程 stdout 和 stderr 以进行日志记录
- 我希望能够从主程序的菜单项中终止进程
杀戮让我头疼。我相信,当我阅读 stdout 和 stderr 时,我必须在额外的线程/进程中执行此操作以保持图标响应。所以我使用 fork() 创建了一个子进程并调用了子进程setsid()
。subprocess
然后该子进程使用模块调用jackd
from subprocess import PIPE, STDOUT, Popen
def runAndLog(self, cmd):
po = Popen(cmd, stdout=PIPE, stderr=STDOUT)
line = po.stdout.readline()
while line:
print(line.rstrip())
line = po.stdout.readline()
self.runAndLog(["jackd","-R", "-P80", "-t5000", "-dfirewire", "-r44100", "-p256", "-n3"])
现在我希望我可以让我的分叉子进程进入同一个进程组,这样我就可以一次杀死两者,但令我惊讶的是,我Popen
创建了一个新的进程组和一个新的会话:
PID PPID PGID SID COMMAND
5790 5788 5788 31258 python (parent, main)
5791 5790 5791 5791 python (forked child after setsid - ok)
5804 5791 5804 5804 jackd (grandchild created by Popen)
因此,杀死孩子不会杀死孙子,我看不出有任何干净的方法可以让孙子的 PID(5804)知道以main
明确地杀死它。我可能会使用一些信号诡计让垂死的孩子杀死孙子,但我犹豫不决。
我也不能setpgid
在 jackd 进程上使用强制它进入孩子的进程组,因为它的 SID 与我孩子的 SID 不同。
我相信我要么
- 必须说服 Popen 不要创建新会话,或者
- 使用一个魔力低于 的模块
subprocess
,但它仍然允许我阅读 stdout 和 stderr。
但我也不知道该怎么做。诚然,我对进程组的了解有些有限。
/home/martin >python --version
Python 2.7.1
10 月 12 日更新
我发现新会话不是由python创建的,而是由jackd
它自己创建的。当我用 替换 jackd 时xterm
,一切都很好。
PID PPID PGID SID COMMAND
12239 4024 12239 4024 python (parent, main)
12244 12239 12244 12244 python (forked child after setsid - ok)
12249 12244 12244 12244 xterm (grandchild has same PGID and SID - ok)
我也发现了这个
这些杰克时代调用 setsid() 以使自己成为新的流程组负责人
只剩下选择
- 让 jack 的 PID 为人所知
main
并明确地杀死它,或者 - 让垂死的孩子杀死 杀死杰克德
对此有何建议?
.