无法在Java中启动子进程中SIGQUIT的信号处理程序

时间:2017-03-23 16:38:41

标签: java linux signals

这是this one的后续问题。

举个简单的例子:

public class Main
{
    public static void main(String[] args) throws Exception
    {
        Runtime.getRuntime().exec("./child");

        // This is just so that the JVM does not exit
        Thread.sleep(1000 * 1000);
    }
}

这是孩子的过程:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void handle_sigquit(int sig) {
  printf("Signal %d received\n", sig);
  exit(1);
}

int main(int argc, char **argv) {
  signal(SIGQUIT, &handle_sigquit);
  sleep(1000);
}

如您所见,我在子进程中明确设置了一个信号处理程序。

当我从shell运行此进程时,我可以发送一个SIGQUIT;信号被正确接收和处理。但是,如果我从Java启动该过程(我在Linux上使用openjdk6),则不会传递信号。这是为什么?

1 个答案:

答案 0 :(得分:2)

java(OpenJDK 6)默认阻止子进程中的SIGQUIT。阻塞的信号在fork和exec之间仍然被阻塞。您可以通过查看子进程的procfs状态文件在Linux上看到此信息:

$ grep Sig /proc/11246/status
SigPnd: 0000000000000000
SigBlk: 0000000000000004
SigIgn: 0000000000000000
SigCgt: 0000000000000000

您可以使用以下命令在非线程进程中取消阻止SIGQUIT:

sigemptyset(&set);
sigaddset(&set, SIGQUIT);
sigprocmask(SIG_UNBLOCK, &set, NULL);

请注意,您的printfs不会出现在终端窗口中; java将用管道替换子进程的stdin,stdout和stderr,并读取进程的stdout,你会做类似的事情

Process p=Runtime.getRuntime().exec("./child");
InputStream stdout = p.getInputStream();