我正在开发一个将集成到客户端代码中的库(C ++)。 这个lib会产生一些子进程,并且必须监视它们,一旦它们死掉就会重新生成它们(出于任何原因)。 我需要使用vfork和exec来生成这些子进程。
我知道我必须使用信号处理程序来处理SIGCHLD并调用waitpid来检测哪个孩子死了。 但是,用户代码可能使用相同的想法来处理自己的子进程。
如果我打电话给waitpid,我会检索有关任何可能死亡的儿童过程的信息(我或不是)。 如果垂死的过程是我的,没问题......快乐的情况。 但是,如果它来自用户,他没有得到任何有关该信息的信息,因为我已经调用了waitpid。
我该如何解决这个问题?
我的第一个想法是使用流程组。 我第一次分叉时,我会得到子pid并将其保存为进程组ID。 我创建的每个孩子,我都会将它设置为这个pid。 你们认为这是一个不错的选择吗? (我遇到了麻烦)。
我的第二个想法是将信号处理程序重置为原始处理程序(或者只是调用它)。 如果我重新加载信号,原始处理程序将能够获得它。 之后我必须重新安装我的信号处理程序。 这会是一个不错的选择吗?
我的第三个选择是使用INFO(扩展信号处理程序)。 我相信死亡过程的pid将在信息结构中提供。 如果这是我的一个孩子,我会给waitpid打电话,那没关系。 如果那不是我的,我会打电话给原始的信号处理程序。 这会是一个不错的选择吗?
只是最后一个问题。 为了能够调用原始信号处理程序,我是否应该总是恢复它们并重新加载信号,或者只是将其称为函数调用就足够了?
非常感谢你的帮助。
答案 0 :(得分:1)
另一种选择可能是首先产生一个子进程,它通过你喜欢的任何IPC机制与你的主进程通信。然后,从该新进程中生成多个子进程,这使您可以完全控制子进程终止的方式。
答案 1 :(得分:1)
如果它是通用库(对于任何第三方),您应该尝试避免这样的构造。如果无法避免使用,请非常仔细地记录信号处理。
如果与lib链接的程序与信号一起播放,则可能发生许多复杂情况,并且lib无法正确处理它们,而不会以意外方式影响程序。考虑到程序可能有多个线程或处理其他信号:在任何一种情况下,它都可能同时改变SIGCHILD
的信号处理并破坏你的逻辑。
也许在lib中提供一个函数可能会更好,你可以让程序负责在信号SIGCHILD
(对于你创建的PID)来的时候调用它,这样程序就可以自由地处理它了表示它的意愿。
答案 2 :(得分:0)
这篇文章只是为了澄清我的解决方案。
我决定不再在主流程中使用信号处理程序了。除非必要,否则lib不应处理信号。
从主进程中,我创建了一个管道调用一个单独的二进制文件,它将自己变成一个守护进程。这样,由此产生的进程将不是主进程的子进程。
要把它变成一个守护神,我就把它分开。 fork的父级只打印子级的PID,因此主进程可以将其返回(通过管道)。子进程将umask设置为零,创建一个新的SID,将当前目录更改为“/”并重新打开STDIN,STDOUT和STDERR(全部为/ dev / null)。这样孩子现在就是一个守护神。
这个守护者负责产生我的所有进程。 所有这些(包括deamon)都使用套接字回复主进程。
主进程向守护进程发送信号(SIGINT将其及其所有子进程,SIGUSER1和2关闭到预定义的动作)。
感谢所有帮助过这里的人。