Annotation of embedaddon/lighttpd/src/lighttpd-angel.c, revision 1.1.1.2

1.1.1.2 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       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>