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>