Java:如何在子进程

时间:2015-11-02 15:18:25

标签: java linux libc

确保父进程终止时子进程终止是棘手的。我发现一个强大的解决方案from Python in Linux是指示内核在父进程使用prctl(PR_SET_PDEATHSIG, SIGTERM)终止时终止子进程。考虑到prctl()来自C标准库,大概可能从C或C ++开始。

有几个关于如何在Java中杀死子进程的问题,请参阅例如[1]。 但是,我发现的任何内容都不如使用prctl()的方法强大。如果父接收SIGKILL,或者他们需要修改子代码,大多数解决方案将失败。通过让操作系统为我们完成工作,无论父进程发生什么情况,都会成功终止子进程,并且不需要修改子代码。

如何在从Java ProcessBuilder中生成的子进程中调用prctl(PR_SET_PDEATHSIG, SIGTERM)

1 个答案:

答案 0 :(得分:3)

你可以用一点C来做,只要你不担心一些条件,并明白它会有局限性。

prctl(PR_SET_PDEATHSIG, …)系统调用是linux内核的一部分,并且有一些规则 - 它不会生存fork(),它不会生存exec()到setuid / setgid二进制文件。

限制是:

  • 这是一个简单的程序,如果你从子进程中启动其他东西,杀死一些东西,除非你设置了一些限制。
  • 它不会在可执行模型(例如32-> 64bit)之间工作,这是相对罕见的
  • 它不能使用静态链接二进制文件(罕见)

考虑到这些限制,我们可以从一些将调用此系统调用的C创建一个小的预加载库。所以,例如:

#include <sys/prctl.h>
#include <sys/types.h>
#include <signal.h>

__attribute__((constructor))
static void on_load() {
    prctl(PR_SET_PDEATHSIG, SIGTERM);
}

使用gcc -fPIC -shared -o term_death.so term_death.c

编译

当您使用LD_PRELOAD环境变量以及此二进制文件的完整路径时,任何启动的程序将在其父进程被终止时发送SIGTERM

这是来自C方面的设置 - 我们现在有一个帮助程序库,它将允许您要求的行为。

从java端开始工作。

我们需要将.so的完整路径注入到ProcessBuilder的LD_PRELOAD环境变量中,如下所示:

ProcessBuilder pb = new ProcessBuilder();
Map<String, String> env = pb.environment();
env.put("LD_PRELOAD", "/home/me/development/experiments/term_death.so");

再次,您需要指定.so的路径,以便可以加载它。

当您pb.start()时,它将继承LD_PRELOAD环境变量。在加载可执行文件时,它会运行on_load代码(因为它被标记为构造函数)并且表示当父进程终止时进程将收到SIGTERM

这有点难看,但应该解决这个问题。