File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / lighttpd-angel.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:35:00 2016 UTC (7 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, HEAD
lighttpd 1.4.41

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>