处理Java中的SIGCHLD信号

3
我有一个Java进程,它可以重新启动一个Linux进程,该进程会生成两个守护进程并退出。(这是HAProxy的包装器,已配置为有两个进程的守护进程)
每次重新启动后,进程表中都会有两个僵尸进程。为了防止这些僵尸进程,我已经实现了以下措施:
final static SignalHandler _signalHandler = new SignalHandler() {

    @Override
    public void handle(Signal signal) {
        LOG.info("Received signal: {}",signal.getName());
    }
};

public HaproxyWrapper() {
    Signal.handle(new Signal("CHLD"), _signalHandler);
    LOG.info("Registered SIGCHLD signal handler");
}

在输出中我看到了"Registered SIGCHLD"日志,但从未看到"Received signal: SIGCHLD"。

我做错了吗?

或者,“最简单的可能性”-我可以创建一个名为start_haproxy.sh的shell脚本,用它来调用haproxy并处理SIGCHLD。如何在bash中处理SIGCHLD?(处理->忽略)

谢谢。


当你收到这个时,子进程已经退出了。但是为什么这会对你有帮助呢 - 子进程存在于守护进程中。 - laune
Laune,请您详细说明一下。Child(haproxy)有两个子进程。因此,我们有一个祖父-父母-孩子的情况:haproxyWrapper(存活)--> haproxy(死亡)--> haproxy守护进程1,2(存活)。 - JRun
haproxWrapper会接收到SIGCHLD信号。如果这些守护进程真的是守护进程,它们不应该成为僵尸进程,而且在包装器中知道haproxy死亡也没有帮助。 - laune
HAproxy死亡的原因是什么? - laune
@laune 这就是 HAProxy 在守护进程模式下的工作方式:主进程启动两个工作进程,然后退出。 - JRun
2个回答

3
我很确定Java已经忽略了SIGCHLD信号,这就是为什么不能捕获它的原因。只有正在运行的进程才会收到该信号,如果你使用“Process.waitFor()”,你将被通知一个子进程已经结束。
僵尸进程指的是无法终止的进程,即它们在应该死亡之后继续存在,通常是由于操作系统中存在问题导致的。我猜想你可能担心孤儿进程,也就是当一个进程的父进程已经死亡时。
最简单的方法是让父进程等待其子进程结束。
顺便说一下,守护进程经常作为孤儿进程运行。你确定这真的是一个问题吗?

是的,如果我有一百行像这样的代码:“101 31988 0.0 0.0 0 0?Zs 09:42 0:00 [haproxy] <defunct>”,那就是个问题。所以在我的情况下,是Java ProcessBuilder调用HAProxy创建了两个进程并死亡。我不确定是Java的问题,还是HAProxy的问题,或者是我的问题 :) - JRun
我非常确定Java已经忽略了SIGCHLD信号,这就是为什么你无法捕获它。我成功地为SIGCHLD安装了一个信号处理程序:https://github.com/jumarko/clojure-experiments/blob/master/src/clojure_experiments/java/processes.clj#L73-L74。我找到的唯一相关的事情是这个Bug,但那真的很旧了。 - Juraj Martinka

1
如果其父进程仍然存在但尚未对子进程进行wait,则会存在僵尸进程。为什么Java不这样做,我不知道。如果父进程退出,则子进程将简单地重新分配到PID 1(init); 在这种情况下,它不能成为僵尸进程。这是双重分叉被使用的一个原因(确保守护程序在启动时立即被重新分配给init,因为其直接父进程已经退出)。

解决它的简单方法是使用正确的守护进程shell脚本。根据您的Linux发行版,您可能已经有一个可以实现此目的的实用程序(例如,start-stop-daemon)。否则,您需要类似于以下内容:

#/bin/bash
(nohup /path/to/program 0<&- &>/dev/null &)&

这个程序执行所需的双重 fork。有一种更长但更彻底的方法可以在此处找到。


你好,谢谢。我试过了:Java现在按照你指定的脚本运行。但仍然有僵尸进程:一个被'root'所拥有,[haproxy_sigchld] <defunct>,以及两个之前的,由101所拥有,[haproxy] <defunct>。 - JRun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接