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 <stdio.h>
17 #include <errno.h>
18 #include <signal.h>
19 #include <unistd.h> /* _exit() execvp() fork() */
20
21 #define BINPATH SBIN_DIR"/lighttpd"
22
23 static volatile sig_atomic_t restart = 0;
24 static pid_t pid = -1;
25
26 __attribute_cold__
signal_handler(int sig)27 static void signal_handler (int sig)
28 {
29 if (pid <= 0) return;
30
31 if (sig == SIGHUP) {
32 /* trigger graceful shutdown of lighttpd, then restart lighttpd */
33 sig = SIGINT;
34 restart = -1;
35 }
36
37 /* forward signal to the child */
38 kill(pid, sig);
39 }
40
41 __attribute_cold__
signal_setup(void)42 static void signal_setup (void)
43 {
44 signal(SIGCHLD, SIG_DFL);
45 signal(SIGALRM, SIG_DFL);
46
47 signal(SIGPIPE, SIG_IGN);
48
49 signal(SIGINT, signal_handler);
50 signal(SIGTERM, signal_handler);
51 signal(SIGUSR1, signal_handler);
52 signal(SIGHUP, signal_handler);
53 }
54
55 __attribute_cold__
main(int argc,char ** argv)56 int main (int argc, char **argv)
57 {
58 UNUSED(argc);
59 *(const char **)&argv[0] = BINPATH;
60 #ifdef __COVERITY__
61 __coverity_tainted_data_sanitize__(argv);
62 #endif
63
64 signal_setup();
65
66 do {
67
68 if (-1 == pid) {
69 pid = fork();
70 if (-1 == pid) return -1;
71 if (0 == pid) {
72 /* intentionally pass argv params */
73 /* coverity[tainted_string : FALSE] */
74 execvp(argv[0], argv);
75 _exit(1);
76 }
77 }
78
79 int exitcode = 0;
80 if ((pid_t)-1 == waitpid(pid, &exitcode, 0)) {
81 if (errno == ECHILD) break; /* child exists; should not happen */
82 continue;
83 }
84
85 const char *msg = NULL;
86 int code = 0;
87 if (WIFEXITED(exitcode)) {
88 code = WEXITSTATUS(exitcode);
89 msg = "%s.%d: child (pid=%d) exited normally with exitcode: %d\n";
90 }
91 else if (WIFSIGNALED(exitcode)) {
92 code = WTERMSIG(exitcode);
93 msg = "%s.%d: child (pid=%d) exited unexpectedly with signal %d, "
94 "restarting\n";
95 restart = -1;
96 }
97 if (msg)
98 fprintf(stderr, msg, __FILE__, __LINE__, pid, code);
99
100 pid = restart; /* -1 for restart, 0 to exit */
101 restart = 0;
102
103 } while (pid != 0);
104
105 return 0;
106 }
107