我有一个(至少对我来说)有趣的问题:在某些情况下,我无法可靠地和可移植地获取子进程的信息。我正在尝试让一个名为AllTray的应用程序在某些奇怪的情况下正常工作,其中它的子进程会生成一个子进程,然后退出。 AllTray 的任务基本上是将应用程序停靠到任务托盘中,这通常是指定为 AllTray 要调用的命令行(即,
大多数GUI软件在AllTray下运行得很好。它在其窗口上设置_NET_WM_PID属性(或小部件库这样做),一切都很好,因为_NET_WM_PID == fork()的子进程。然而,在某些情况下(例如在运行oowriter时,或者在为KDE编写的软件(如K3b)下运行时),AllTray运行的子进程是一个包装器,无论是shell脚本(如OO.o的情况)还是一个奇怪的程序,它fork()和exec()自身并有效地将自己后台化,因为父进程很早就死了。
我想到不收割我的子进程,以便在进程表中保留我的孙子的父进程ID,以便我可以通过从底部到顶部遍历家族树将它们链接回到我身上。然而,这并不起作用:一旦我的子进程死亡并变成僵尸,系统就认为我的孙子进程是一个孤儿,并且init会接管它。这似乎至少在Linux 2.6和NetBSD上是这种情况;我会认为这可能是常态,而POSIX似乎没有指定这种情况,所以我希望相反。
由于这种方法行不通,我考虑使用
alltray xterm
会启动 xterm,并在 AllTray 中管理它)。大多数GUI软件在AllTray下运行得很好。它在其窗口上设置_NET_WM_PID属性(或小部件库这样做),一切都很好,因为_NET_WM_PID == fork()的子进程。然而,在某些情况下(例如在运行oowriter时,或者在为KDE编写的软件(如K3b)下运行时),AllTray运行的子进程是一个包装器,无论是shell脚本(如OO.o的情况)还是一个奇怪的程序,它fork()和exec()自身并有效地将自己后台化,因为父进程很早就死了。
我想到不收割我的子进程,以便在进程表中保留我的孙子的父进程ID,以便我可以通过从底部到顶部遍历家族树将它们链接回到我身上。然而,这并不起作用:一旦我的子进程死亡并变成僵尸,系统就认为我的孙子进程是一个孤儿,并且init会接管它。这似乎至少在Linux 2.6和NetBSD上是这种情况;我会认为这可能是常态,而POSIX似乎没有指定这种情况,所以我希望相反。
由于这种方法行不通,我考虑使用
LD_PRELOAD
拦截子进程对fork()
的调用,并将信息传递回父进程。然而,我担心这不如理想的解决方案具有可移植性,因为不同系统对动态链接器执行LD_PRELOAD
等操作的规则不同。对于Linux系统上没有设置helper库的setuid/setgid GUI应用程序也无法工作。总的来说,这对我来说是一个糟糕的想法,感觉很hackish。
因此,我希望有人能提出如何解决这个问题的想法,或者如果依赖像LD_PRELOAD
这样的机制是我唯一的选择,除了打补丁内核(这是不会发生的),还有什么其他的选择吗?