added a first version of the lighttpd-angel process
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@1981 152afb58-edef-0310-8abb-c4023f1b3aa9svn/tags/lighttpd-1.4.18
parent
29fdd34abd
commit
b333dd7efa
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* angel process for lighttpd
|
||||
*
|
||||
* the purpose is the run as root all the time and handle:
|
||||
* - restart on crash
|
||||
* - spawn on HUP to allow graceful restart
|
||||
* - ...
|
||||
*
|
||||
* it has to stay safe and small to be trustable
|
||||
*/
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define BINPATH SBIN_DIR"/lighttpd"
|
||||
|
||||
static siginfo_t last_sigterm_info;
|
||||
static siginfo_t last_sighup_info;
|
||||
|
||||
static volatile sig_atomic_t start_process = 1;
|
||||
static volatile sig_atomic_t graceful_restart = 0;
|
||||
static volatile pid_t pid = -1;
|
||||
|
||||
static void sigaction_handler(int sig, siginfo_t *si, void *context) {
|
||||
int exitcode;
|
||||
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
memcpy(&last_sigterm_info, si, sizeof(*si));
|
||||
|
||||
/** forward the sig to the child */
|
||||
kill(pid, sig);
|
||||
break;
|
||||
case SIGHUP: /** do a graceful restart */
|
||||
memcpy(&last_sighup_info, si, sizeof(*si));
|
||||
|
||||
/** do a graceful shutdown on the main process and start a new child */
|
||||
kill(pid, SIGINT);
|
||||
|
||||
usleep(5 * 1000); /** wait 5 microsec */
|
||||
|
||||
start_process = 1;
|
||||
break;
|
||||
case SIGCHLD:
|
||||
/** a child died, de-combie it */
|
||||
wait(&exitcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int is_shutdown = 0;
|
||||
struct sigaction act;
|
||||
|
||||
/**
|
||||
* we are running as root BEWARE
|
||||
*/
|
||||
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &act, NULL);
|
||||
sigaction(SIGUSR1, &act, NULL);
|
||||
|
||||
act.sa_sigaction = sigaction_handler;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
|
||||
sigaction(SIGINT, &act, NULL);
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
sigaction(SIGHUP, &act, NULL);
|
||||
sigaction(SIGALRM, &act, NULL);
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
|
||||
/* check that the compiled in path has the right user,
|
||||
*
|
||||
* BEWARE: there is a race between the check here and the exec later
|
||||
*/
|
||||
|
||||
while (!is_shutdown) {
|
||||
int exitcode = 0;
|
||||
|
||||
if (start_process) {
|
||||
pid = fork();
|
||||
|
||||
if (0 == pid) {
|
||||
/* i'm the child */
|
||||
|
||||
argv[0] = BINPATH;
|
||||
|
||||
execvp(BINPATH, argv);
|
||||
|
||||
exit(1);
|
||||
} else if (-1 == pid) {
|
||||
/** error */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* I'm the angel */
|
||||
start_process = 0;
|
||||
}
|
||||
|
||||
if ((pid_t)-1 == waitpid(pid, &exitcode, 0)) {
|
||||
switch (errno) {
|
||||
case EINTR:
|
||||
/* someone sent a signal ...
|
||||
* do we have to shutdown or restart the process */
|
||||
break;
|
||||
case ECHILD:
|
||||
/**
|
||||
* make sure we are not in a race between the signal handler
|
||||
* and the process restart */
|
||||
if (!start_process) is_shutdown = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/** process went away */
|
||||
|
||||
if (WIFEXITED(exitcode)) {
|
||||
/** normal exit */
|
||||
|
||||
is_shutdown = 1;
|
||||
|
||||
fprintf(stderr, "%s.%d: child (pid=%d) exited normally with exitcode: %d\n",
|
||||
__FILE__, __LINE__,
|
||||
pid,
|
||||
WEXITSTATUS(exitcode));
|
||||
|
||||
} else if (WIFSIGNALED(exitcode)) {
|
||||
/** got a signal */
|
||||
|
||||
fprintf(stderr, "%s.%d: child (pid=%d) exited unexpectedly with signal %d, restarting\n",
|
||||
__FILE__, __LINE__,
|
||||
pid,
|
||||
WTERMSIG(exitcode));
|
||||
|
||||
start_process = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue