4

我正在开发一个将集成到客户端代码中的库(C++)。该库将产生一些子进程,并且必须监视它们以在它们死后立即重新生成它们(出于任何原因)。我需要使用 vfork 和 exec 来生成这些子进程。

我知道我必须使用信号处理程序来处理 SIGCHLD 并调用 waitpid 来检测哪个孩子已经死了。但是,用户代码可能使用相同的想法来处理自己的子进程。

如果我调用 waitpid,我将检索有关任何可能死亡的子进程的信息(我的或不是我的)。如果死亡过程是我的,没问题……幸福的情况。但是,如果是来自用户,他不会得到任何相关信息,因为我已经调用了 waitpid。

我该如何解决这个问题?

我的第一个想法是使用进程组。第一次分叉时,我会获取子 pid 并将其保存为进程组 ID。我创建的每个孩子,我都会将它的组设置为这个pid。大家觉得这样的选择好不好?(我遇到了麻烦)。

我的第二个想法是将信号处理程序重置为原始处理程序(或直接调用它)。如果我重新发出信号,原始处理程序将能够得到它。之后我必须重新安装我的信号处理程序。会是一个不错的选择吗?

我的第三个选择是使用 INFO(扩展信号处理程序)。我相信消亡过程的pid将在信息结构中可用。如果这是我的一个孩子,我会为此打电话给waitpid,没关系。如果那不是我的,我会调用原始信号处理程序。会是一个不错的选择吗?

最后一个问题。为了能够调用原始信号处理程序,我应该始终恢复它们并重新发出信号还是仅将其作为函数调用来调用就足够了?

非常感谢您的帮助。

4

3 回答 3

1

另一种选择可能是首先生成一个子进程,它通过您喜欢的任何 IPC 机制与您的主进程通信。然后,从该新进程中生成多个子进程,这使您可以完全控制子进程终止的方式。

于 2012-05-29T22:13:47.633 回答
1

如果它是一个通用库(对于任何第 3 方),您应该尽量避免这种构造。如果无法避免使用它,请非常仔细地记录信号处理。

如果与 lib 链接的程序使用信号,可能会发生许多复杂的情况,并且 lib 没有机会正确处理它们,而不会以意想不到的方式影响程序。考虑程序可能有多个线程或处理您不处理的其他信号:在任何一种情况下,它都可能SIGCHILD同时更改信号处理并破坏您的逻辑。

也许在 lib 中提供一个函数可能会更好,当信号(对于您创建的 PID)到来时,您让它由程序负责调用它,SIGCHILD这样程序仍然可以自由地按照它的意愿处理其信号。

于 2012-05-30T06:28:50.800 回答
0

这篇文章只是为了澄清我的解决方案。

我决定不再在主进程中使用信号处理程序。除非必要,否则库不应处理信号。

在主进程中,我创建了一个管道,调用了一个单独的二进制文件,它将自己变成了一个守护进程。这样,由此产生的进程将不是主进程的子进程。

为了把它变成一个守护进程,我只是分叉它。fork 的父进程只打印子进程的 PID,以便主进程可以将其取回(通过管道)。子进程将 umask 设置为零,创建一个新的 SID,将当前目录更改为“/”并重新打开 STDIN、STDOUT 和 STDERR(全部为 /dev/null)。这样,孩子现在是一个恶魔。

这个守护进程负责生成我所有的进程。所有这些(包括守护进程)都使用套接字与主进程通信。

主进程向守护进程发送信号(SIGINT 关闭它及其所有子进程,SIGUSER1 和 2 到预定义的操作)。

感谢所有在这里提供帮助的人。

于 2012-06-01T02:35:57.480 回答