in src/native/unix/native/jsvc-unix.c [1298:1406]
static int run_controller(arg_data *args, home_data *data, uid_t uid, gid_t gid)
{
pid_t pid = 0;
int restarts = 0;
struct sigaction act;
controller_pid = getpid();
/*
* Install signal handlers for the parent process.
* These will be replaced in the child process.
*/
memset(&act, '\0', sizeof(act));
act.sa_sigaction = controller;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_SIGINFO;
sigaction(SIGHUP, &act, NULL);
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGINT, &act, NULL);
/* We have to fork: this process will become the controller and the other
will be the child */
while ((pid = fork()) != -1) {
time_t laststart;
int status = 0;
/* We forked (again), if this is the child, we go on normally */
if (pid == 0)
exit(child(args, data, uid, gid));
laststart = time(NULL);
/* We are in the controller, we have to forward all interesting signals
to the child, and wait for it to die */
controlled = pid;
#ifdef OS_CYGWIN
SetTerm(cygwincontroller);
#endif
while (waitpid(pid, &status, 0) != pid) {
/* Wait for process */
}
/* The child must have exited cleanly */
if (WIFEXITED(status)) {
status = WEXITSTATUS(status);
/* Delete the pid file */
if (args->vers != true && args->chck != true && status != 122)
remove_pid_file(args, pid);
/* If the child got out with 123 he wants to be restarted */
/* See java_abort123 (we use this return code to restart when the JVM aborts) */
if (!stopping) {
if (status == 123) {
if (args->restarts == 0) {
log_debug("Service failure, restarts disabled");
return 1;
}
if (args->restarts != -1 && args->restarts <= restarts) {
log_debug("Service failure, restart limit reached, aborting");
return 1;
}
log_debug("Reloading service");
restarts++;
/* prevent looping */
if (laststart + 60 > time(NULL)) {
log_debug("Waiting 60 s to prevent looping");
sleep(60);
}
continue;
}
}
/* If the child got out with 0 he is shutting down */
if (status == 0) {
log_debug("Service shut down");
return 0;
}
/* Otherwise we don't rerun it */
log_error("Service exit with a return value of %d", status);
return 1;
}
else {
if (WIFSIGNALED(status)) {
log_error("Service killed by signal %d", WTERMSIG(status));
/* prevent looping */
if (!stopping) {
if (laststart + 60 > time(NULL)) {
log_debug("Waiting 60 s to prevent looping");
sleep(60);
}
/* Normal or user controlled termination, reset restart counter */
restarts = 0;
continue;
}
}
log_error("Service did not exit cleanly", status);
return 1;
}
}
/* Got out of the loop? A fork() failed then. */
log_error("Cannot decouple controller/child processes");
return 1;
}