简体   繁体   中英

Handling SIGCHLD signal in Java

I have a Java process, that (re)starts a Linux process, which spawns two daemonised child processes and dies. (It's a wrapper to HAProxy, which is configured as a daemon with 2 Processes)

On every re-start, the process table has two more Zombie processes. To prevent these Zombies, I have implemented the following:

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");
}

I see the 'Registered SIGCHLD' log in the output, but never the 'Received signal: SIGCHLD'.

Am I doing this wrong?

Alternatively, 'the simplest thing that could possibly work' - I could create a shell script called start_haproxy.sh which will both call haproxy and handle the SIGCHLD. How do I handle SIGCHLD in bash? (handle -> ignore)

Thanks.

I am pretty sure that Java already ignores the SIGCHLD which is why you can't trap it. Only a running process would get this signal and if you Process.waitFor() you will be notified that a child process has died.

Zombie processes are ones which cannot be killed, ie they live on after they should have died, usually due to a problem in the OS. I suspect you are concerned about orphaned processes, ie when you have a process whose parent had died.

The simplest way to prevent that is to make your parent wait for it's children to die.

BTW daemon processes often run as orphaned processes. Are you sure this is really a problem?

A zombie process exists if its parent still exists but has not yet done a wait for the child. Why Java isn't doing that, I don't know. If the parent exits, the child simply reparents to PID 1 ( init ); in this case it can't become a Zombie. This is one reason why double forking is utilized (ensuring that the daemon is reparented to init as soon as it starts as its immediate parent will already have exited).

The easy way around it is to use a shell script which properly daemonizes. Depending on your Linux distribution, you may already have a utility that does this (eg start-stop-daemon . Otherwise, you want something like

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

which does the requisite double fork. There is a longer but more thorough way to do it here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM