假设我有一个进程,它只生成一个子进程。现在,当父进程由于某种原因(正常或不正常,通过kill, ^C,断言失败或其他任何原因)退出时,我希望子进程死亡。如何正确地做到这一点?


关于stackoverflow的一些类似问题:

(前面问过)当父进程退出的时候,我怎么能让子进程退出呢? (稍后问)用fork()创建的子进程会在父进程被杀死时自动被杀死吗?


关于Windows的stackoverflow也有类似的问题:

如何在Windows中自动销毁子进程? 当父进程被杀死时,杀死子进程


当前回答

子进程是否有连接父进程的管道?如果是这样,那么写入时会收到SIGPIPE,读取时会收到EOF——这些情况都可以检测到。

其他回答

子进程是否有连接父进程的管道?如果是这样,那么写入时会收到SIGPIPE,读取时会收到EOF——这些情况都可以检测到。

通过在prctl()系统调用中指定PR_SET_PDEATHSIG选项,子进程可以要求内核在父进程死亡时传递SIGHUP(或其他信号),就像这样:

prctl(PR_SET_PDEATHSIG, SIGHUP);

详见man 2 prctl。

编辑:这是linux专用的

我认为不可能保证只使用标准POSIX调用。就像现实生活一样,一旦孩子被孕育出来,它就有了自己的生命。

父进程可以捕获大多数可能的终止事件,并尝试在此时终止子进程,但总有一些无法捕获。

例如,没有进程可以捕获SIGKILL。当内核处理这个信号时,它将杀死指定的进程,而不通知该进程。

扩展一下类比——唯一的另一种标准方式是,当孩子发现自己不再有父母时自杀。

使用prctl(2)有一种linux独有的方法——请参阅其他答案。

安装一个陷阱处理程序来捕获SIGINT,如果你的子进程还活着,它就会杀死它,尽管其他的帖子是正确的,它不会捕获SIGKILL。

以独占访问的方式打开一个.lockfile,并让子进程尝试打开它——如果打开成功,子进程应该退出

即使7年过去了,我刚刚遇到这个问题,因为我正在运行SpringBoot应用程序,需要在开发期间启动webpack-dev-server,并需要在后端进程停止时杀死它。

我尝试使用Runtime.getRuntime()。addShutdownHook,但它在Windows 10上工作,但在Windows 7上不工作。

我已经将其更改为使用一个专门的线程来等待进程退出或用于InterruptedException,这似乎在两个Windows版本上都正确工作。

private void startWebpackDevServer() {
    String cmd = isWindows() ? "cmd /c gradlew webPackStart" : "gradlew webPackStart";
    logger.info("webpack dev-server " + cmd);

    Thread thread = new Thread(() -> {

        ProcessBuilder pb = new ProcessBuilder(cmd.split(" "));
        pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        pb.directory(new File("."));

        Process process = null;
        try {
            // Start the node process
            process = pb.start();

            // Wait for the node process to quit (blocking)
            process.waitFor();

            // Ensure the node process is killed
            process.destroyForcibly();
            System.setProperty(WEBPACK_SERVER_PROPERTY, "true");
        } catch (InterruptedException | IOException e) {
            // Ensure the node process is killed.
            // InterruptedException is thrown when the main process exit.
            logger.info("killing webpack dev-server", e);
            if (process != null) {
                process.destroyForcibly();
            }
        }

    });

    thread.start();
}