2015-11-02 54 views
1

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

关于如何杀死Java中的子进程有几个问题,请参阅[1]。 但是,我发现的东西和使用prctl()的方法一样强大。如果父母收到SIGKILL,或者他们需要修改子代码,则大多数解决方案都会失败。通过让操作系统为我们完成这项工作,无论父母发生什么事情,孩子总是会被成功杀死,并且子代码不需要修改。

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

回答

3

您可以用位C的去做,只要你不担心几个条件,并了解它有局限性。

prctl(PR_SET_PDEATHSIG, …)系统调用是Linux内核的一部分,并有一对夫妇的规则 - 它不下去fork(),它不下去exec()成的setuid/setgid的二进制文件。

限制是:

  • 这是一个简单的程序,它会如果从子进程启动别的东西,除非你把一些限制可怕的杀人的事情。
  • 它不会跨越可执行模型(如32-> 64位),这是比较少见的工作
  • 它不会与静态链接的二进制文件(罕见)

考虑到这些局限性的工作,我们可以从一些调用此系统调用的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方面的工作。

我们需要注入的完整路径。所以到了的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

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