#ifndef __supervise_h
#define __supervise_h
#include "config.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#ifndef HAVE_SYSLOG
static void inline supervise(char *x)
{
fatal("You probably don't want to supervise when you cannot log");
}
#else
static int supervised_pid = -1;
static int supervised_quit = 0;
static void handle_sign(int signo)
{
if (supervised_pid != -1) {
kill(supervised_pid, signo);
supervised_quit = 1;
}
}
static void inline supervise(char *x)
{
int fd, status;
int super_pid;
/* GOOD DAEMON PRACTICES */
/* do first fork */
signal(SIGCHLD, SIG_IGN);
switch (fork()) {
case -1: cfatal("fork: %s");
case 0: break;
default: exit(0);
};
/* be a proper daemon */
fd = open("/dev/null", O_RDWR);
if (fd != 0) { close(0); dup2(fd, 0); }
if (fd != 1) { close(1); dup2(fd, 1); }
if (fd != 2) { close(2); dup2(fd, 2); }
if (fd > 2) { close(fd); }
super_pid = getpid();
#ifdef HAVE_SETSID
/* change session ID if possible */
(void) setsid();
#endif
/* signore Sigpipe */
signal(SIGPIPE, SIG_IGN);
/* we want child notification */
signal(SIGCHLD, SIG_DFL);
/* setup other signals */
signal(SIGSTOP, handle_sign);
signal(SIGCONT, handle_sign);
signal(SIGTERM, handle_sign);
signal(SIGHUP, handle_sign);
signal(SIGINT, handle_sign);
/* do second fork */
restart_from_child_l:
switch ((supervised_pid = fork())) {
case -1: cfatal("fork: %s");
case 0: /* child */ return;
};
/* pid file */
if (x && *x == '/') {
FILE *fp;
fp = fopen(x, "w");
fprintf(fp, "%d\n", super_pid);
fclose(fp);
}
wait_some_more_l:
#ifdef HAVE_WAITPID
waitpid(supervised_pid, &status, 0);
#else
#ifdef HAVE_WAIT4
wait4(supervised_pid, &status, 0, NULL);
#else
while (wait(&status) != supervised_pid);
#endif
#endif
if (kill(supervised_pid, 0) == -1) {
sleep(1); /* go to sleep for 1 second */
if ((volatile)supervised_quit)
exit(0);
/* wasn't supposed to be dead yet... */
goto restart_from_child_l;
}
supervised_quit = 0;
goto wait_some_more_l;
}
#endif
#endif
syntax highlighted by Code2HTML, v. 0.9.1