javalinuxsignal-handlingsigchldruntime-environment

Java signal chaining


I've got a program with a specialized Process-type class which handles executing the processes natively on Linux.

It does not use Java's Process class at all, because it needs to do some special handling of the process. Because of this, it also installs its own signal handler for SIGCHLD, so that it knows when a process exits.

However, I just added a Runtime.exec() call in my code, which apparently installs its own signal handler for SIGCHLD, which means that I never get a SIGCHLD again, which is bad. I've followed the signal-chaining instructions from oracle, but the same problem happens, I never get a SIGCHLD.

So, the basic question is this: is it possible to chain SIGCHLD in Java?


Solution

  • libjsig does not help, because SIGCHLD handler is installed by libjava, not by JVM itself.

    sigaction(SIGCHLD, ...) with sa_handler = SIG_DFL is called only once by Java Class Library in the static initializer of java.lang.UNIXProcess.

    Now you have the following options to work-around this.

    1. The easiest one. Just install your signal handler after initialization of java.lang.UNIXProcess.

    2. Create your own LD_PRELOAD hook that will intercept sigaction and ignore it when called with SIGCHLD and SIG_DFL arguments:

    E.g.

    #define _GNU_SOURCE
    #include <signal.h>
    #include <dlfcn.h>
    #include <stddef.h>
    
    int sigaction(int signum, const struct sigaction* act, struct sigaction* oldact) {
        static int (*real_sa)(int, const struct sigaction*, struct sigaction*) = NULL;
    
        if (signum == SIGCHLD && act->sa_handler == SIG_DFL) {
            return 0;
        }
    
        if (real_sa == NULL) {
            real_sa = dlsym(RTLD_NEXT, "sigaction");
        }
        return real_sa(signum, act, oldact);
    }