Browse Source

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-c4023f1b3aa9
svn/tags/lighttpd-1.4.18
Jan Kneschke 15 years ago
parent
commit
b333dd7efa
  1. 6
      src/Makefile.am
  2. 154
      src/lighttpd-angel.c

6
src/Makefile.am

@ -1,12 +1,14 @@
AM_CFLAGS = $(FAM_CFLAGS)
noinst_PROGRAMS=proc_open lemon # simple-fcgi #graphic evalo bench ajp ssl error_test adserver gen-license
sbin_PROGRAMS=lighttpd
sbin_PROGRAMS=lighttpd lighttpd-angel
bin_PROGRAMS=spawn-fcgi
LEMON=$(top_builddir)/src/lemon
lemon_SOURCES=lemon.c
lighttpd_angel_SOURCES=lighttpd-angel.c
#simple_fcgi_SOURCES=simple-fcgi.c
#simple_fcgi_LDADD=-lfcgi
@ -254,7 +256,7 @@ hdr = server.h buffer.h network.h log.h keyvalue.h \
splaytree.h proc_open.h status_counter.h \
mod_magnet_cache.h
DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\"" -DSBIN_DIR="\"$(sbindir)\""
lighttpd_SOURCES = $(src)
lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS)

154
src/lighttpd-angel.c

@ -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…
Cancel
Save