假设我有一个进程,它只生成一个子进程。现在,当父进程由于某种原因(正常或不正常,通过kill, ^C,断言失败或其他任何原因)退出时,我希望子进程死亡。如何正确地做到这一点?
关于stackoverflow的一些类似问题:
(前面问过)当父进程退出的时候,我怎么能让子进程退出呢? (稍后问)用fork()创建的子进程会在父进程被杀死时自动被杀死吗?
关于Windows的stackoverflow也有类似的问题:
如何在Windows中自动销毁子进程? 当父进程被杀死时,杀死子进程
假设我有一个进程,它只生成一个子进程。现在,当父进程由于某种原因(正常或不正常,通过kill, ^C,断言失败或其他任何原因)退出时,我希望子进程死亡。如何正确地做到这一点?
关于stackoverflow的一些类似问题:
(前面问过)当父进程退出的时候,我怎么能让子进程退出呢? (稍后问)用fork()创建的子进程会在父进程被杀死时自动被杀死吗?
关于Windows的stackoverflow也有类似的问题:
如何在Windows中自动销毁子进程? 当父进程被杀死时,杀死子进程
当前回答
如果你无法修改子进程,你可以尝试以下方法:
int pipes[2];
pipe(pipes)
if (fork() == 0) {
close(pipes[1]); /* Close the writer end in the child*/
dup2(pipes[0], STDIN_FILENO); /* Use reader end as stdin (fixed per maxschlepzig */
exec("sh -c 'set -o monitor; child_process & read dummy; kill %1'")
}
close(pipes[0]); /* Close the reader end in the parent */
这将在启用作业控制的shell进程中运行子进程。子进程在后台生成。shell等待换行符(或EOF),然后终止子进程。
当父进程死亡时——不管是什么原因——它将关闭管道的一端。子shell将从read中获得一个EOF,并继续杀死后台的子进程。
其他回答
子进程是否有连接父进程的管道?如果是这样,那么写入时会收到SIGPIPE,读取时会收到EOF——这些情况都可以检测到。
安装一个陷阱处理程序来捕获SIGINT,如果你的子进程还活着,它就会杀死它,尽管其他的帖子是正确的,它不会捕获SIGKILL。
以独占访问的方式打开一个.lockfile,并让子进程尝试打开它——如果打开成功,子进程应该退出
我在过去通过在“子”中运行“原始”代码和在“父”中运行“衍生”代码来实现这一点(也就是说:你在fork()之后反转了通常意义上的测试)。然后在“衍生”代码中捕获SIGCHLD…
对你来说可能不行,但管用的时候很可爱。
以防它与任何人相关,当我从c++派生子进程中的JVM实例时,我可以让JVM实例在父进程完成后正确终止的唯一方法是执行以下操作。如果这不是最好的方法,希望有人能在评论中提供反馈。
1)在通过execv启动Java应用程序之前,在fork子进程上调用prctl(PR_SET_PDEATHSIG, SIGHUP)
2)在Java应用程序中添加一个shutdown钩子,轮询直到其父PID等于1,然后执行一个硬的Runtime.getRuntime().halt(0)。轮询是通过启动运行ps命令的单独shell来完成的(参见:如何在Linux上的Java或JRuby中找到我的PID ?)
130118年编辑:
这似乎不是一个可靠的解决方案。我仍然在努力理解发生的事情的细微差别,但在屏幕/SSH会话中运行这些应用程序时,有时仍然会遇到孤立的JVM进程。
Instead of polling for the PPID in the Java app, I simply had the shutdown hook perform cleanup followed by a hard halt as above. Then I made sure to invoke waitpid in the C++ parent app on the spawned child process when it was time to terminate everything. This seems to be a more robust solution, as the child process ensures that it terminates, while the parent uses existing references to make sure that its children terminate. Compare this to the previous solution which had the parent process terminate whenever it pleased, and had the children try to figure out if they had been orphaned before terminating.
这个解决方案对我很有效:
将stdin管道传递给子管道-您不必向流中写入任何数据。 Child从stdin无限读取到EOF。EOF表示父节点已经离开。 这是一种万无一失、便于携带的检测父节点何时离开的方法。即使父线程崩溃,操作系统也会关闭管道。
这是针对一个工作者类型的进程,它的存在只有在父进程存在时才有意义。