Browse Source
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@1981 152afb58-edef-0310-8abb-c4023f1b3aa9svn/tags/lighttpd-1.4.18
2 changed files with 158 additions and 2 deletions
@ -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