Annotation of embedaddon/lighttpd/src/lighttpd-angel.c, revision 1.1
1.1 ! misho 1: /**
! 2: * angel process for lighttpd
! 3: *
! 4: * the purpose is the run as root all the time and handle:
! 5: * - restart on crash
! 6: * - spawn on HUP to allow graceful restart
! 7: * - ...
! 8: *
! 9: * it has to stay safe and small to be trustable
! 10: */
! 11:
! 12: #include <sys/wait.h>
! 13:
! 14: #include <stdlib.h>
! 15: #include <stdio.h>
! 16: #include <string.h>
! 17: #include <errno.h>
! 18: #include <unistd.h>
! 19: #include <time.h>
! 20: #include <signal.h>
! 21:
! 22: #define BINPATH SBIN_DIR"/lighttpd"
! 23:
! 24: static siginfo_t last_sigterm_info;
! 25: static siginfo_t last_sighup_info;
! 26:
! 27: static volatile sig_atomic_t start_process = 1;
! 28: static volatile pid_t pid = -1;
! 29:
! 30: #define UNUSED(x) ( (void)(x) )
! 31:
! 32: static void sigaction_handler(int sig, siginfo_t *si, void *context) {
! 33: int exitcode;
! 34:
! 35: UNUSED(context);
! 36: switch (sig) {
! 37: case SIGINT:
! 38: case SIGTERM:
! 39: memcpy(&last_sigterm_info, si, sizeof(*si));
! 40:
! 41: /** forward the sig to the child */
! 42: kill(pid, sig);
! 43: break;
! 44: case SIGHUP: /** do a graceful restart */
! 45: memcpy(&last_sighup_info, si, sizeof(*si));
! 46:
! 47: /** do a graceful shutdown on the main process and start a new child */
! 48: kill(pid, SIGINT);
! 49:
! 50: usleep(5 * 1000); /** wait 5 microsec */
! 51:
! 52: start_process = 1;
! 53: break;
! 54: case SIGCHLD:
! 55: /** a child died, de-combie it */
! 56: wait(&exitcode);
! 57: break;
! 58: }
! 59: }
! 60:
! 61: int main(int argc, char **argv) {
! 62: int is_shutdown = 0;
! 63: struct sigaction act;
! 64:
! 65: UNUSED(argc);
! 66:
! 67: /**
! 68: * we are running as root BEWARE
! 69: */
! 70:
! 71: memset(&act, 0, sizeof(act));
! 72: act.sa_handler = SIG_IGN;
! 73: sigaction(SIGPIPE, &act, NULL);
! 74: sigaction(SIGUSR1, &act, NULL);
! 75:
! 76: act.sa_sigaction = sigaction_handler;
! 77: sigemptyset(&act.sa_mask);
! 78: act.sa_flags = SA_SIGINFO;
! 79:
! 80: sigaction(SIGINT, &act, NULL);
! 81: sigaction(SIGTERM, &act, NULL);
! 82: sigaction(SIGHUP, &act, NULL);
! 83: sigaction(SIGALRM, &act, NULL);
! 84: sigaction(SIGCHLD, &act, NULL);
! 85:
! 86: /* check that the compiled in path has the right user,
! 87: *
! 88: * BEWARE: there is a race between the check here and the exec later
! 89: */
! 90:
! 91: while (!is_shutdown) {
! 92: int exitcode = 0;
! 93:
! 94: if (start_process) {
! 95: pid = fork();
! 96:
! 97: if (0 == pid) {
! 98: /* i'm the child */
! 99:
! 100: argv[0] = BINPATH;
! 101:
! 102: execvp(BINPATH, argv);
! 103:
! 104: exit(1);
! 105: } else if (-1 == pid) {
! 106: /** error */
! 107:
! 108: return -1;
! 109: }
! 110:
! 111: /* I'm the angel */
! 112: start_process = 0;
! 113: }
! 114:
! 115: if ((pid_t)-1 == waitpid(pid, &exitcode, 0)) {
! 116: switch (errno) {
! 117: case EINTR:
! 118: /* someone sent a signal ...
! 119: * do we have to shutdown or restart the process */
! 120: break;
! 121: case ECHILD:
! 122: /**
! 123: * make sure we are not in a race between the signal handler
! 124: * and the process restart */
! 125: if (!start_process) is_shutdown = 1;
! 126: break;
! 127: default:
! 128: break;
! 129: }
! 130: } else {
! 131: /** process went away */
! 132:
! 133: if (WIFEXITED(exitcode)) {
! 134: /** normal exit */
! 135:
! 136: is_shutdown = 1;
! 137:
! 138: fprintf(stderr, "%s.%d: child (pid=%d) exited normally with exitcode: %d\n",
! 139: __FILE__, __LINE__,
! 140: pid,
! 141: WEXITSTATUS(exitcode));
! 142:
! 143: } else if (WIFSIGNALED(exitcode)) {
! 144: /** got a signal */
! 145:
! 146: fprintf(stderr, "%s.%d: child (pid=%d) exited unexpectedly with signal %d, restarting\n",
! 147: __FILE__, __LINE__,
! 148: pid,
! 149: WTERMSIG(exitcode));
! 150:
! 151: start_process = 1;
! 152: }
! 153: }
! 154: }
! 155:
! 156: return 0;
! 157: }
! 158:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>