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>