Annotation of embedaddon/lighttpd/src/server.c, revision 1.1.1.3
1.1.1.3 ! misho 1: #include "first.h"
! 2:
1.1 misho 3: #include "server.h"
4: #include "buffer.h"
5: #include "network.h"
6: #include "log.h"
7: #include "keyvalue.h"
8: #include "response.h"
9: #include "request.h"
10: #include "chunk.h"
11: #include "http_chunk.h"
12: #include "fdevent.h"
13: #include "connections.h"
14: #include "stat_cache.h"
15: #include "plugin.h"
16: #include "joblist.h"
17: #include "network_backends.h"
18: #include "version.h"
19:
20: #include <sys/types.h>
21: #include <sys/time.h>
22: #include <sys/stat.h>
23:
24: #include <string.h>
25: #include <errno.h>
26: #include <fcntl.h>
27: #include <unistd.h>
28: #include <stdlib.h>
29: #include <time.h>
30: #include <signal.h>
31: #include <assert.h>
32: #include <locale.h>
33:
34: #include <stdio.h>
35:
36: #ifdef HAVE_GETOPT_H
37: # include <getopt.h>
38: #endif
39:
40: #ifdef HAVE_VALGRIND_VALGRIND_H
41: # include <valgrind/valgrind.h>
42: #endif
43:
44: #ifdef HAVE_SYS_WAIT_H
45: # include <sys/wait.h>
46: #endif
47:
48: #ifdef HAVE_PWD_H
49: # include <grp.h>
50: # include <pwd.h>
51: #endif
52:
53: #ifdef HAVE_SYS_RESOURCE_H
54: # include <sys/resource.h>
55: #endif
56:
57: #ifdef HAVE_SYS_PRCTL_H
58: # include <sys/prctl.h>
59: #endif
60:
61: #ifdef USE_OPENSSL
62: # include <openssl/err.h>
63: #endif
64:
65: #ifndef __sgi
66: /* IRIX doesn't like the alarm based time() optimization */
67: /* #define USE_ALARM */
68: #endif
69:
70: #ifdef HAVE_GETUID
71: # ifndef HAVE_ISSETUGID
72:
73: static int l_issetugid(void) {
74: return (geteuid() != getuid() || getegid() != getgid());
75: }
76:
77: # define issetugid l_issetugid
78: # endif
79: #endif
80:
1.1.1.3 ! misho 81: static int oneshot_fd = 0;
1.1 misho 82: static volatile sig_atomic_t srv_shutdown = 0;
83: static volatile sig_atomic_t graceful_shutdown = 0;
84: static volatile sig_atomic_t handle_sig_alarm = 1;
85: static volatile sig_atomic_t handle_sig_hup = 0;
86: static volatile sig_atomic_t forwarded_sig_hup = 0;
87:
88: #if defined(HAVE_SIGACTION) && defined(SA_SIGINFO)
89: static volatile siginfo_t last_sigterm_info;
90: static volatile siginfo_t last_sighup_info;
91:
92: static void sigaction_handler(int sig, siginfo_t *si, void *context) {
93: static siginfo_t empty_siginfo;
94: UNUSED(context);
95:
96: if (!si) si = &empty_siginfo;
97:
98: switch (sig) {
99: case SIGTERM:
100: srv_shutdown = 1;
101: last_sigterm_info = *si;
102: break;
103: case SIGINT:
104: if (graceful_shutdown) {
105: srv_shutdown = 1;
106: } else {
107: graceful_shutdown = 1;
108: }
109: last_sigterm_info = *si;
110:
111: break;
112: case SIGALRM:
113: handle_sig_alarm = 1;
114: break;
115: case SIGHUP:
116: /**
117: * we send the SIGHUP to all procs in the process-group
118: * this includes ourself
119: *
120: * make sure we only send it once and don't create a
121: * infinite loop
122: */
123: if (!forwarded_sig_hup) {
124: handle_sig_hup = 1;
125: last_sighup_info = *si;
126: } else {
127: forwarded_sig_hup = 0;
128: }
129: break;
130: case SIGCHLD:
131: break;
132: }
133: }
134: #elif defined(HAVE_SIGNAL) || defined(HAVE_SIGACTION)
135: static void signal_handler(int sig) {
136: switch (sig) {
137: case SIGTERM: srv_shutdown = 1; break;
138: case SIGINT:
139: if (graceful_shutdown) srv_shutdown = 1;
140: else graceful_shutdown = 1;
141:
142: break;
143: case SIGALRM: handle_sig_alarm = 1; break;
144: case SIGHUP: handle_sig_hup = 1; break;
145: case SIGCHLD: break;
146: }
147: }
148: #endif
149:
150: #ifdef HAVE_FORK
1.1.1.3 ! misho 151: static int daemonize(void) {
! 152: int pipefd[2];
! 153: pid_t pid;
1.1 misho 154: #ifdef SIGTTOU
155: signal(SIGTTOU, SIG_IGN);
156: #endif
157: #ifdef SIGTTIN
158: signal(SIGTTIN, SIG_IGN);
159: #endif
160: #ifdef SIGTSTP
161: signal(SIGTSTP, SIG_IGN);
162: #endif
1.1.1.3 ! misho 163:
! 164: if (pipe(pipefd) < 0) exit(-1);
! 165:
! 166: if (0 > (pid = fork())) exit(-1);
! 167:
! 168: if (0 < pid) {
! 169: char buf;
! 170: ssize_t bytes;
! 171:
! 172: close(pipefd[1]);
! 173: /* parent waits for grandchild to be ready */
! 174: do {
! 175: bytes = read(pipefd[0], &buf, sizeof(buf));
! 176: } while (bytes < 0 && EINTR == errno);
! 177: close(pipefd[0]);
! 178:
! 179: if (bytes <= 0) {
! 180: /* closed fd (without writing) == failure in grandchild */
! 181: fputs("daemonized server failed to start; check error log for details\n", stderr);
! 182: exit(-1);
! 183: }
! 184:
! 185: exit(0);
! 186: }
! 187:
! 188: close(pipefd[0]);
1.1 misho 189:
190: if (-1 == setsid()) exit(0);
191:
192: signal(SIGHUP, SIG_IGN);
193:
194: if (0 != fork()) exit(0);
195:
196: if (0 != chdir("/")) exit(0);
1.1.1.3 ! misho 197:
! 198: fd_close_on_exec(pipefd[1]);
! 199: return pipefd[1];
1.1 misho 200: }
201: #endif
202:
203: static server *server_init(void) {
204: int i;
205: FILE *frandom = NULL;
206:
207: server *srv = calloc(1, sizeof(*srv));
1.1.1.2 misho 208: force_assert(srv);
1.1 misho 209: #define CLEAN(x) \
210: srv->x = buffer_init();
211:
212: CLEAN(response_header);
213: CLEAN(parse_full_path);
214: CLEAN(ts_debug_str);
215: CLEAN(ts_date_str);
216: CLEAN(errorlog_buf);
217: CLEAN(response_range);
218: CLEAN(tmp_buf);
219: srv->empty_string = buffer_init_string("");
220: CLEAN(cond_check_buf);
221:
222: CLEAN(srvconf.errorlog_file);
223: CLEAN(srvconf.breakagelog_file);
224: CLEAN(srvconf.groupname);
225: CLEAN(srvconf.username);
226: CLEAN(srvconf.changeroot);
227: CLEAN(srvconf.bindhost);
228: CLEAN(srvconf.event_handler);
229: CLEAN(srvconf.pid_file);
230:
231: CLEAN(tmp_chunk_len);
232: #undef CLEAN
233:
234: #define CLEAN(x) \
235: srv->x = array_init();
236:
237: CLEAN(config_context);
238: CLEAN(config_touched);
239: CLEAN(status);
240: #undef CLEAN
241:
242: for (i = 0; i < FILE_CACHE_MAX; i++) {
243: srv->mtime_cache[i].mtime = (time_t)-1;
244: srv->mtime_cache[i].str = buffer_init();
245: }
246:
247: if ((NULL != (frandom = fopen("/dev/urandom", "rb")) || NULL != (frandom = fopen("/dev/random", "rb")))
248: && 1 == fread(srv->entropy, sizeof(srv->entropy), 1, frandom)) {
249: unsigned int e;
250: memcpy(&e, srv->entropy, sizeof(e) < sizeof(srv->entropy) ? sizeof(e) : sizeof(srv->entropy));
251: srand(e);
252: srv->is_real_entropy = 1;
253: } else {
254: unsigned int j;
255: srand(time(NULL) ^ getpid());
256: srv->is_real_entropy = 0;
257: for (j = 0; j < sizeof(srv->entropy); j++)
258: srv->entropy[j] = rand();
259: }
260: if (frandom) fclose(frandom);
261:
262: srv->cur_ts = time(NULL);
263: srv->startup_ts = srv->cur_ts;
264:
265: srv->conns = calloc(1, sizeof(*srv->conns));
1.1.1.2 misho 266: force_assert(srv->conns);
1.1 misho 267:
268: srv->joblist = calloc(1, sizeof(*srv->joblist));
1.1.1.2 misho 269: force_assert(srv->joblist);
1.1 misho 270:
271: srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
1.1.1.2 misho 272: force_assert(srv->fdwaitqueue);
1.1 misho 273:
274: srv->srvconf.modules = array_init();
275: srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
276: srv->srvconf.network_backend = buffer_init();
277: srv->srvconf.upload_tempdirs = array_init();
278: srv->srvconf.reject_expect_100_with_417 = 1;
1.1.1.3 ! misho 279: srv->srvconf.xattr_name = buffer_init_string("Content-Type");
! 280: srv->srvconf.http_header_strict = 1;
! 281: srv->srvconf.http_host_strict = 1; /*(implies http_host_normalize)*/
! 282: srv->srvconf.http_host_normalize = 0;
! 283: srv->srvconf.high_precision_timestamps = 0;
1.1 misho 284:
285: /* use syslog */
286: srv->errorlog_fd = STDERR_FILENO;
287: srv->errorlog_mode = ERRORLOG_FD;
288:
289: srv->split_vals = array_init();
290:
291: return srv;
292: }
293:
294: static void server_free(server *srv) {
295: size_t i;
296:
297: for (i = 0; i < FILE_CACHE_MAX; i++) {
298: buffer_free(srv->mtime_cache[i].str);
299: }
300:
1.1.1.3 ! misho 301: if (oneshot_fd > 0) {
! 302: close(oneshot_fd);
! 303: }
! 304:
1.1 misho 305: #define CLEAN(x) \
306: buffer_free(srv->x);
307:
308: CLEAN(response_header);
309: CLEAN(parse_full_path);
310: CLEAN(ts_debug_str);
311: CLEAN(ts_date_str);
312: CLEAN(errorlog_buf);
313: CLEAN(response_range);
314: CLEAN(tmp_buf);
315: CLEAN(empty_string);
316: CLEAN(cond_check_buf);
317:
318: CLEAN(srvconf.errorlog_file);
319: CLEAN(srvconf.breakagelog_file);
320: CLEAN(srvconf.groupname);
321: CLEAN(srvconf.username);
322: CLEAN(srvconf.changeroot);
323: CLEAN(srvconf.bindhost);
324: CLEAN(srvconf.event_handler);
325: CLEAN(srvconf.pid_file);
326: CLEAN(srvconf.modules_dir);
327: CLEAN(srvconf.network_backend);
1.1.1.3 ! misho 328: CLEAN(srvconf.xattr_name);
1.1 misho 329:
330: CLEAN(tmp_chunk_len);
331: #undef CLEAN
332:
333: #if 0
334: fdevent_unregister(srv->ev, srv->fd);
335: #endif
336: fdevent_free(srv->ev);
337:
338: free(srv->conns);
339:
340: if (srv->config_storage) {
341: for (i = 0; i < srv->config_context->used; i++) {
342: specific_config *s = srv->config_storage[i];
343:
344: if (!s) continue;
345:
346: buffer_free(s->document_root);
347: buffer_free(s->server_name);
348: buffer_free(s->server_tag);
349: buffer_free(s->ssl_pemfile);
350: buffer_free(s->ssl_ca_file);
351: buffer_free(s->ssl_cipher_list);
352: buffer_free(s->ssl_dh_file);
353: buffer_free(s->ssl_ec_curve);
354: buffer_free(s->error_handler);
1.1.1.3 ! misho 355: buffer_free(s->error_handler_404);
1.1 misho 356: buffer_free(s->errorfile_prefix);
357: array_free(s->mimetypes);
358: buffer_free(s->ssl_verifyclient_username);
359: #ifdef USE_OPENSSL
360: SSL_CTX_free(s->ssl_ctx);
1.1.1.2 misho 361: EVP_PKEY_free(s->ssl_pemfile_pkey);
362: X509_free(s->ssl_pemfile_x509);
363: if (NULL != s->ssl_ca_file_cert_names) sk_X509_NAME_pop_free(s->ssl_ca_file_cert_names, X509_NAME_free);
1.1 misho 364: #endif
365: free(s);
366: }
367: free(srv->config_storage);
368: srv->config_storage = NULL;
369: }
370:
371: #define CLEAN(x) \
372: array_free(srv->x);
373:
374: CLEAN(config_context);
375: CLEAN(config_touched);
376: CLEAN(status);
377: CLEAN(srvconf.upload_tempdirs);
378: #undef CLEAN
379:
380: joblist_free(srv, srv->joblist);
381: fdwaitqueue_free(srv, srv->fdwaitqueue);
382:
383: if (srv->stat_cache) {
384: stat_cache_free(srv->stat_cache);
385: }
386:
387: array_free(srv->srvconf.modules);
388: array_free(srv->split_vals);
389:
390: #ifdef USE_OPENSSL
391: if (srv->ssl_is_init) {
392: CRYPTO_cleanup_all_ex_data();
393: ERR_free_strings();
1.1.1.3 ! misho 394: #if OPENSSL_VERSION_NUMBER >= 0x10100000L \
! 395: && !defined(LIBRESSL_VERSION_NUMBER)
! 396: /*(OpenSSL libraries handle thread init and deinit)
! 397: * https://github.com/openssl/openssl/pull/1048 */
! 398: #elif OPENSSL_VERSION_NUMBER >= 0x10000000L
! 399: ERR_remove_thread_state(NULL);
! 400: #else
1.1 misho 401: ERR_remove_state(0);
1.1.1.3 ! misho 402: #endif
1.1 misho 403: EVP_cleanup();
404: }
405: #endif
406:
407: free(srv);
408: }
409:
1.1.1.3 ! misho 410: static void remove_pid_file(server *srv, int *pid_fd) {
! 411: if (!buffer_string_is_empty(srv->srvconf.pid_file) && 0 <= *pid_fd) {
! 412: if (0 != ftruncate(*pid_fd, 0)) {
! 413: log_error_write(srv, __FILE__, __LINE__, "sbds",
! 414: "ftruncate failed for:",
! 415: srv->srvconf.pid_file,
! 416: errno,
! 417: strerror(errno));
! 418: }
! 419: }
! 420: if (0 <= *pid_fd) {
! 421: close(*pid_fd);
! 422: *pid_fd = -1;
! 423: }
! 424: if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
! 425: buffer_string_is_empty(srv->srvconf.changeroot)) {
! 426: if (0 != unlink(srv->srvconf.pid_file->ptr)) {
! 427: if (errno != EACCES && errno != EPERM) {
! 428: log_error_write(srv, __FILE__, __LINE__, "sbds",
! 429: "unlink failed for:",
! 430: srv->srvconf.pid_file,
! 431: errno,
! 432: strerror(errno));
! 433: }
! 434: }
! 435: }
! 436: }
! 437:
! 438:
! 439: static server_socket * server_oneshot_getsock(server *srv, sock_addr *cnt_addr) {
! 440: server_socket *srv_socket, *srv_socket_wild = NULL;
! 441: size_t i;
! 442: for (i = 0; i < srv->srv_sockets.used; ++i) {
! 443: srv_socket = srv->srv_sockets.ptr[i];
! 444: if (cnt_addr->plain.sa_family != srv_socket->addr.plain.sa_family) continue;
! 445: switch (cnt_addr->plain.sa_family) {
! 446: case AF_INET:
! 447: if (srv_socket->addr.ipv4.sin_port != cnt_addr->ipv4.sin_port) continue;
! 448: if (srv_socket->addr.ipv4.sin_addr.s_addr == cnt_addr->ipv4.sin_addr.s_addr) {
! 449: return srv_socket;
! 450: }
! 451: if (srv_socket->addr.ipv4.sin_addr.s_addr == htonl(INADDR_ANY)) {
! 452: srv_socket_wild = srv_socket;
! 453: }
! 454: continue;
! 455: #ifdef HAVE_IPV6
! 456: case AF_INET6:
! 457: if (srv_socket->addr.ipv6.sin6_port != cnt_addr->ipv6.sin6_port) continue;
! 458: if (0 == memcmp(&srv_socket->addr.ipv6.sin6_addr, &cnt_addr->ipv6.sin6_addr, sizeof(struct in6_addr))) {
! 459: return srv_socket;
! 460: }
! 461: if (0 == memcmp(&srv_socket->addr.ipv6.sin6_addr, &in6addr_any, sizeof(struct in6_addr))) {
! 462: srv_socket_wild = srv_socket;
! 463: }
! 464: continue;
! 465: #endif
! 466: #ifdef HAVE_SYS_UN_H
! 467: case AF_UNIX:
! 468: if (0 == strcmp(srv_socket->addr.un.sun_path, cnt_addr->un.sun_path)) {
! 469: return srv_socket;
! 470: }
! 471: continue;
! 472: #endif
! 473: default: continue;
! 474: }
! 475: }
! 476:
! 477: if (NULL != srv_socket_wild) {
! 478: return srv_socket_wild;
! 479: } else if (srv->srv_sockets.used) {
! 480: return srv->srv_sockets.ptr[0];
! 481: } else {
! 482: log_error_write(srv, __FILE__, __LINE__, "s", "no sockets configured");
! 483: return NULL;
! 484: }
! 485: }
! 486:
! 487:
! 488: static int server_oneshot_init(server *srv, int fd) {
! 489: /* Note: does not work with netcat due to requirement that fd be socket.
! 490: * STDOUT_FILENO was not saved earlier in startup, and that is to where
! 491: * netcat expects output to be sent. Since lighttpd expects connections
! 492: * to be sockets, con->fd is where output is sent; separate fds are not
! 493: * stored for input and output, but netcat has different fds for stdin
! 494: * and * stdout. To support netcat, would additionally need to avoid
! 495: * S_ISSOCK(), getsockname(), and getpeername() below, reconstructing
! 496: * addresses from environment variables:
! 497: * NCAT_LOCAL_ADDR NCAT_LOCAL_PORT
! 498: * NCAT_REMOTE_ADDR NCAT_REMOTE_PORT
! 499: * NCAT_PROTO
! 500: */
! 501: connection *con;
! 502: server_socket *srv_socket;
! 503: sock_addr cnt_addr;
! 504: socklen_t cnt_len;
! 505: struct stat st;
! 506:
! 507: if (0 != fstat(fd, &st)) {
! 508: log_error_write(srv, __FILE__, __LINE__, "ss", "fstat:", strerror(errno));
! 509: return 0;
! 510: }
! 511:
! 512: if (!S_ISSOCK(st.st_mode)) {
! 513: /* require that fd is a socket
! 514: * (modules might expect STDIN_FILENO and STDOUT_FILENO opened to /dev/null) */
! 515: log_error_write(srv, __FILE__, __LINE__, "s", "lighttpd -1 stdin is not a socket");
! 516: return 0;
! 517: }
! 518:
! 519: cnt_len = sizeof(cnt_addr);
! 520: if (0 != getsockname(fd, (struct sockaddr *)&cnt_addr, &cnt_len)) {
! 521: log_error_write(srv, __FILE__, __LINE__, "ss", "getsockname:", strerror(errno));
! 522: return 0;
! 523: }
! 524:
! 525: srv_socket = server_oneshot_getsock(srv, &cnt_addr);
! 526: if (NULL == srv_socket) return 0;
! 527:
! 528: cnt_len = sizeof(cnt_addr);
! 529: if (0 != getpeername(fd, (struct sockaddr *)&cnt_addr, &cnt_len)) {
! 530: log_error_write(srv, __FILE__, __LINE__, "ss", "getpeername:", strerror(errno));
! 531: return 0;
! 532: }
! 533:
! 534: if (cnt_addr.plain.sa_family != AF_UNIX) {
! 535: network_accept_tcp_nagle_disable(fd);
! 536: }
! 537:
! 538: con = connection_accepted(srv, srv_socket, &cnt_addr, fd);
! 539: if (NULL == con) return 0;
! 540:
! 541: connection_state_machine(srv, con);
! 542: return 1;
! 543: }
! 544:
! 545:
1.1 misho 546: static void show_version (void) {
547: #ifdef USE_OPENSSL
548: # define TEXT_SSL " (ssl)"
549: #else
550: # define TEXT_SSL
551: #endif
552: char *b = PACKAGE_DESC TEXT_SSL \
553: " - a light and fast webserver\n" \
554: "Build-Date: " __DATE__ " " __TIME__ "\n";
555: ;
556: #undef TEXT_SSL
1.1.1.3 ! misho 557: write_all(STDOUT_FILENO, b, strlen(b));
1.1 misho 558: }
559:
560: static void show_features (void) {
561: const char features[] = ""
562: #ifdef USE_SELECT
563: "\t+ select (generic)\n"
564: #else
565: "\t- select (generic)\n"
566: #endif
567: #ifdef USE_POLL
568: "\t+ poll (Unix)\n"
569: #else
570: "\t- poll (Unix)\n"
571: #endif
572: #ifdef USE_LINUX_SIGIO
573: "\t+ rt-signals (Linux 2.4+)\n"
574: #else
575: "\t- rt-signals (Linux 2.4+)\n"
576: #endif
577: #ifdef USE_LINUX_EPOLL
578: "\t+ epoll (Linux 2.6)\n"
579: #else
580: "\t- epoll (Linux 2.6)\n"
581: #endif
582: #ifdef USE_SOLARIS_DEVPOLL
583: "\t+ /dev/poll (Solaris)\n"
584: #else
585: "\t- /dev/poll (Solaris)\n"
586: #endif
587: #ifdef USE_SOLARIS_PORT
588: "\t+ eventports (Solaris)\n"
589: #else
590: "\t- eventports (Solaris)\n"
591: #endif
592: #ifdef USE_FREEBSD_KQUEUE
593: "\t+ kqueue (FreeBSD)\n"
594: #else
595: "\t- kqueue (FreeBSD)\n"
596: #endif
597: #ifdef USE_LIBEV
598: "\t+ libev (generic)\n"
599: #else
600: "\t- libev (generic)\n"
601: #endif
602: "\nNetwork handler:\n\n"
603: #if defined USE_LINUX_SENDFILE
604: "\t+ linux-sendfile\n"
605: #else
606: "\t- linux-sendfile\n"
607: #endif
608: #if defined USE_FREEBSD_SENDFILE
609: "\t+ freebsd-sendfile\n"
610: #else
611: "\t- freebsd-sendfile\n"
612: #endif
1.1.1.3 ! misho 613: #if defined USE_DARWIN_SENDFILE
! 614: "\t+ darwin-sendfile\n"
! 615: #else
! 616: "\t- darwin-sendfile\n"
! 617: #endif
1.1 misho 618: #if defined USE_SOLARIS_SENDFILEV
619: "\t+ solaris-sendfilev\n"
620: #else
621: "\t- solaris-sendfilev\n"
622: #endif
623: #if defined USE_WRITEV
624: "\t+ writev\n"
625: #else
626: "\t- writev\n"
627: #endif
628: "\t+ write\n"
629: #ifdef USE_MMAP
630: "\t+ mmap support\n"
631: #else
632: "\t- mmap support\n"
633: #endif
634: "\nFeatures:\n\n"
635: #ifdef HAVE_IPV6
636: "\t+ IPv6 support\n"
637: #else
638: "\t- IPv6 support\n"
639: #endif
640: #if defined HAVE_ZLIB_H && defined HAVE_LIBZ
641: "\t+ zlib support\n"
642: #else
643: "\t- zlib support\n"
644: #endif
645: #if defined HAVE_BZLIB_H && defined HAVE_LIBBZ2
646: "\t+ bzip2 support\n"
647: #else
648: "\t- bzip2 support\n"
649: #endif
1.1.1.3 ! misho 650: #if defined(HAVE_CRYPT) || defined(HAVE_CRYPT_R) || defined(HAVE_LIBCRYPT)
1.1 misho 651: "\t+ crypt support\n"
652: #else
653: "\t- crypt support\n"
654: #endif
655: #ifdef USE_OPENSSL
656: "\t+ SSL Support\n"
657: #else
658: "\t- SSL Support\n"
659: #endif
660: #ifdef HAVE_LIBPCRE
661: "\t+ PCRE support\n"
662: #else
663: "\t- PCRE support\n"
664: #endif
665: #ifdef HAVE_MYSQL
666: "\t+ mySQL support\n"
667: #else
668: "\t- mySQL support\n"
669: #endif
670: #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
671: "\t+ LDAP support\n"
672: #else
673: "\t- LDAP support\n"
674: #endif
1.1.1.3 ! misho 675: #ifdef USE_MEMCACHED
1.1 misho 676: "\t+ memcached support\n"
677: #else
678: "\t- memcached support\n"
679: #endif
680: #ifdef HAVE_FAM_H
681: "\t+ FAM support\n"
682: #else
683: "\t- FAM support\n"
684: #endif
685: #ifdef HAVE_LUA_H
686: "\t+ LUA support\n"
687: #else
688: "\t- LUA support\n"
689: #endif
690: #ifdef HAVE_LIBXML_H
691: "\t+ xml support\n"
692: #else
693: "\t- xml support\n"
694: #endif
695: #ifdef HAVE_SQLITE3_H
696: "\t+ SQLite support\n"
697: #else
698: "\t- SQLite support\n"
699: #endif
700: #ifdef HAVE_GDBM_H
701: "\t+ GDBM support\n"
702: #else
703: "\t- GDBM support\n"
704: #endif
705: "\n";
706: show_version();
707: printf("\nEvent Handlers:\n\n%s", features);
708: }
709:
710: static void show_help (void) {
711: #ifdef USE_OPENSSL
712: # define TEXT_SSL " (ssl)"
713: #else
714: # define TEXT_SSL
715: #endif
716: char *b = PACKAGE_DESC TEXT_SSL " ("__DATE__ " " __TIME__ ")" \
717: " - a light and fast webserver\n" \
718: "usage:\n" \
719: " -f <name> filename of the config-file\n" \
720: " -m <name> module directory (default: "LIBRARY_DIR")\n" \
1.1.1.3 ! misho 721: " -i <secs> graceful shutdown after <secs> of inactivity\n" \
! 722: " -1 process single (one) request on stdin socket, then exit\n" \
1.1 misho 723: " -p print the parsed config-file in internal form, and exit\n" \
1.1.1.3 ! misho 724: " -t test config-file syntax, then exit\n" \
! 725: " -tt test config-file syntax, load and init modules, then exit\n" \
1.1 misho 726: " -D don't go to background (default: go to background)\n" \
727: " -v show version\n" \
728: " -V show compile-time features\n" \
729: " -h show this help\n" \
730: "\n"
731: ;
732: #undef TEXT_SSL
733: #undef TEXT_IPV6
1.1.1.3 ! misho 734: write_all(STDOUT_FILENO, b, strlen(b));
1.1 misho 735: }
736:
737: int main (int argc, char **argv) {
738: server *srv = NULL;
739: int print_config = 0;
740: int test_config = 0;
741: int i_am_root;
742: int o;
743: int num_childs = 0;
744: int pid_fd = -1, fd;
745: size_t i;
1.1.1.3 ! misho 746: time_t idle_limit = 0, last_active_ts = time(NULL);
1.1 misho 747: #ifdef HAVE_SIGACTION
748: struct sigaction act;
749: #endif
750: #ifdef HAVE_GETRLIMIT
751: struct rlimit rlim;
752: #endif
753:
1.1.1.3 ! misho 754: #ifdef HAVE_FORK
! 755: int parent_pipe_fd = -1;
! 756: #endif
! 757:
1.1 misho 758: #ifdef USE_ALARM
759: struct itimerval interval;
760:
761: interval.it_interval.tv_sec = 1;
762: interval.it_interval.tv_usec = 0;
763: interval.it_value.tv_sec = 1;
764: interval.it_value.tv_usec = 0;
765: #endif
766:
767: /* for nice %b handling in strfime() */
768: setlocale(LC_TIME, "C");
769:
770: if (NULL == (srv = server_init())) {
771: fprintf(stderr, "did this really happen?\n");
772: return -1;
773: }
774:
775: /* init structs done */
776:
777: srv->srvconf.port = 0;
778: #ifdef HAVE_GETUID
779: i_am_root = (getuid() == 0);
780: #else
781: i_am_root = 0;
782: #endif
783: srv->srvconf.dont_daemonize = 0;
1.1.1.3 ! misho 784: srv->srvconf.preflight_check = 0;
1.1 misho 785:
1.1.1.3 ! misho 786: while(-1 != (o = getopt(argc, argv, "f:m:i:hvVD1pt"))) {
1.1 misho 787: switch(o) {
788: case 'f':
789: if (srv->config_storage) {
790: log_error_write(srv, __FILE__, __LINE__, "s",
791: "Can only read one config file. Use the include command to use multiple config files.");
792:
793: server_free(srv);
794: return -1;
795: }
796: if (config_read(srv, optarg)) {
797: server_free(srv);
798: return -1;
799: }
800: break;
801: case 'm':
802: buffer_copy_string(srv->srvconf.modules_dir, optarg);
803: break;
1.1.1.3 ! misho 804: case 'i': {
! 805: char *endptr;
! 806: long timeout = strtol(optarg, &endptr, 0);
! 807: if (!*optarg || *endptr || timeout < 0) {
! 808: log_error_write(srv, __FILE__, __LINE__, "ss",
! 809: "Invalid idle timeout value:", optarg);
! 810: server_free(srv);
! 811: return -1;
! 812: }
! 813: idle_limit = (time_t)timeout;
! 814: break;
! 815: }
1.1 misho 816: case 'p': print_config = 1; break;
1.1.1.3 ! misho 817: case 't': ++test_config; break;
! 818: case '1': oneshot_fd = dup(STDIN_FILENO); break;
1.1 misho 819: case 'D': srv->srvconf.dont_daemonize = 1; break;
1.1.1.3 ! misho 820: case 'v': show_version(); server_free(srv); return 0;
! 821: case 'V': show_features(); server_free(srv); return 0;
! 822: case 'h': show_help(); server_free(srv); return 0;
1.1 misho 823: default:
824: show_help();
825: server_free(srv);
826: return -1;
827: }
828: }
829:
830: if (!srv->config_storage) {
831: log_error_write(srv, __FILE__, __LINE__, "s",
832: "No configuration available. Try using -f option.");
833:
834: server_free(srv);
835: return -1;
836: }
837:
838: if (print_config) {
839: data_unset *dc = srv->config_context->data[0];
840: if (dc) {
841: dc->print(dc, 0);
842: fprintf(stdout, "\n");
843: } else {
844: /* shouldn't happend */
845: fprintf(stderr, "global config not found\n");
846: }
847: }
848:
849: if (test_config) {
1.1.1.3 ! misho 850: if (1 == test_config) {
! 851: printf("Syntax OK\n");
! 852: } else { /*(test_config > 1)*/
! 853: test_config = 0;
! 854: srv->srvconf.preflight_check = 1;
! 855: srv->srvconf.dont_daemonize = 1;
! 856: buffer_reset(srv->srvconf.pid_file);
! 857: }
1.1 misho 858: }
859:
860: if (test_config || print_config) {
861: server_free(srv);
862: return 0;
863: }
864:
1.1.1.3 ! misho 865: if (oneshot_fd) {
! 866: if (oneshot_fd <= STDERR_FILENO) {
! 867: log_error_write(srv, __FILE__, __LINE__, "s",
! 868: "Invalid fds at startup with lighttpd -1");
! 869: server_free(srv);
! 870: return -1;
! 871: }
! 872: graceful_shutdown = 1;
! 873: srv->sockets_disabled = 1;
! 874: srv->srvconf.dont_daemonize = 1;
! 875: buffer_reset(srv->srvconf.pid_file);
! 876: if (srv->srvconf.max_worker) {
! 877: srv->srvconf.max_worker = 0;
! 878: log_error_write(srv, __FILE__, __LINE__, "s",
! 879: "server one-shot command line option disables server.max-worker config file option.");
! 880: }
! 881: }
! 882:
1.1 misho 883: /* close stdin and stdout, as they are not needed */
884: openDevNull(STDIN_FILENO);
885: openDevNull(STDOUT_FILENO);
886:
887: if (0 != config_set_defaults(srv)) {
888: log_error_write(srv, __FILE__, __LINE__, "s",
889: "setting default values failed");
890: server_free(srv);
891: return -1;
892: }
893:
894: /* UID handling */
895: #ifdef HAVE_GETUID
896: if (!i_am_root && issetugid()) {
897: /* we are setuid-root */
898:
899: log_error_write(srv, __FILE__, __LINE__, "s",
900: "Are you nuts ? Don't apply a SUID bit to this binary");
901:
902: server_free(srv);
903: return -1;
904: }
905: #endif
906:
907: /* check document-root */
1.1.1.3 ! misho 908: if (buffer_string_is_empty(srv->config_storage[0]->document_root)) {
1.1 misho 909: log_error_write(srv, __FILE__, __LINE__, "s",
910: "document-root is not set\n");
911:
912: server_free(srv);
913:
914: return -1;
915: }
916:
917: if (plugins_load(srv)) {
918: log_error_write(srv, __FILE__, __LINE__, "s",
919: "loading plugins finally failed");
920:
921: plugins_free(srv);
922: server_free(srv);
923:
924: return -1;
925: }
926:
927: /* open pid file BEFORE chroot */
1.1.1.3 ! misho 928: if (!buffer_string_is_empty(srv->srvconf.pid_file)) {
1.1 misho 929: if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
930: struct stat st;
931: if (errno != EEXIST) {
932: log_error_write(srv, __FILE__, __LINE__, "sbs",
933: "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
934: return -1;
935: }
936:
937: if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
938: log_error_write(srv, __FILE__, __LINE__, "sbs",
939: "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
940: }
941:
942: if (!S_ISREG(st.st_mode)) {
943: log_error_write(srv, __FILE__, __LINE__, "sb",
944: "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
945: return -1;
946: }
947:
948: if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
949: log_error_write(srv, __FILE__, __LINE__, "sbs",
950: "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
951: return -1;
952: }
953: }
1.1.1.3 ! misho 954: fd_close_on_exec(pid_fd);
1.1 misho 955: }
956:
957: if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
958: /* select limits itself
959: *
960: * as it is a hard limit and will lead to a segfault we add some safety
961: * */
962: srv->max_fds = FD_SETSIZE - 200;
963: } else {
964: srv->max_fds = 4096;
965: }
966:
967: if (i_am_root) {
968: struct group *grp = NULL;
969: struct passwd *pwd = NULL;
970: int use_rlimit = 1;
971:
972: #ifdef HAVE_VALGRIND_VALGRIND_H
973: if (RUNNING_ON_VALGRIND) use_rlimit = 0;
974: #endif
975:
976: #ifdef HAVE_GETRLIMIT
977: if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
978: log_error_write(srv, __FILE__, __LINE__,
979: "ss", "couldn't get 'max filedescriptors'",
980: strerror(errno));
981: return -1;
982: }
983:
984: if (use_rlimit && srv->srvconf.max_fds) {
985: /* set rlimits */
986:
987: rlim.rlim_cur = srv->srvconf.max_fds;
988: rlim.rlim_max = srv->srvconf.max_fds;
989:
990: if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
991: log_error_write(srv, __FILE__, __LINE__,
992: "ss", "couldn't set 'max filedescriptors'",
993: strerror(errno));
994: return -1;
995: }
996: }
997:
998: if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
1.1.1.3 ! misho 999: srv->max_fds = rlim.rlim_cur < (rlim_t)FD_SETSIZE - 200 ? (int)rlim.rlim_cur : (int)FD_SETSIZE - 200;
1.1 misho 1000: } else {
1001: srv->max_fds = rlim.rlim_cur;
1002: }
1003:
1004: /* set core file rlimit, if enable_cores is set */
1005: if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
1006: rlim.rlim_cur = rlim.rlim_max;
1007: setrlimit(RLIMIT_CORE, &rlim);
1008: }
1009: #endif
1010: if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
1011: /* don't raise the limit above FD_SET_SIZE */
1012: if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
1013: log_error_write(srv, __FILE__, __LINE__, "sd",
1014: "can't raise max filedescriptors above", FD_SETSIZE - 200,
1015: "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
1016: return -1;
1017: }
1018: }
1019:
1020:
1021: #ifdef HAVE_PWD_H
1022: /* set user and group */
1.1.1.3 ! misho 1023: if (!buffer_string_is_empty(srv->srvconf.groupname)) {
! 1024: if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
! 1025: log_error_write(srv, __FILE__, __LINE__, "sb",
! 1026: "can't find groupname", srv->srvconf.groupname);
! 1027: return -1;
! 1028: }
! 1029: }
! 1030:
! 1031: if (!buffer_string_is_empty(srv->srvconf.username)) {
1.1 misho 1032: if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
1033: log_error_write(srv, __FILE__, __LINE__, "sb",
1034: "can't find username", srv->srvconf.username);
1035: return -1;
1036: }
1037:
1038: if (pwd->pw_uid == 0) {
1039: log_error_write(srv, __FILE__, __LINE__, "s",
1040: "I will not set uid to 0\n");
1041: return -1;
1042: }
1043:
1.1.1.3 ! misho 1044: if (NULL == grp && NULL == (grp = getgrgid(pwd->pw_gid))) {
! 1045: log_error_write(srv, __FILE__, __LINE__, "sd",
! 1046: "can't find group id", pwd->pw_gid);
1.1 misho 1047: return -1;
1048: }
1.1.1.3 ! misho 1049: }
! 1050:
! 1051: if (NULL != grp) {
1.1 misho 1052: if (grp->gr_gid == 0) {
1053: log_error_write(srv, __FILE__, __LINE__, "s",
1054: "I will not set gid to 0\n");
1055: return -1;
1056: }
1057: }
1058: #endif
1059: /* we need root-perms for port < 1024 */
1060: if (0 != network_init(srv)) {
1061: plugins_free(srv);
1062: server_free(srv);
1063:
1064: return -1;
1065: }
1066: #ifdef HAVE_PWD_H
1067: /*
1068: * Change group before chroot, when we have access
1069: * to /etc/group
1070: * */
1071: if (NULL != grp) {
1.1.1.2 misho 1072: if (-1 == setgid(grp->gr_gid)) {
1073: log_error_write(srv, __FILE__, __LINE__, "ss", "setgid failed: ", strerror(errno));
1074: return -1;
1075: }
1076: if (-1 == setgroups(0, NULL)) {
1077: log_error_write(srv, __FILE__, __LINE__, "ss", "setgroups failed: ", strerror(errno));
1078: return -1;
1079: }
1.1.1.3 ! misho 1080: if (!buffer_string_is_empty(srv->srvconf.username)) {
1.1 misho 1081: initgroups(srv->srvconf.username->ptr, grp->gr_gid);
1082: }
1083: }
1084: #endif
1085: #ifdef HAVE_CHROOT
1.1.1.3 ! misho 1086: if (!buffer_string_is_empty(srv->srvconf.changeroot)) {
1.1 misho 1087: tzset();
1088:
1089: if (-1 == chroot(srv->srvconf.changeroot->ptr)) {
1090: log_error_write(srv, __FILE__, __LINE__, "ss", "chroot failed: ", strerror(errno));
1091: return -1;
1092: }
1093: if (-1 == chdir("/")) {
1094: log_error_write(srv, __FILE__, __LINE__, "ss", "chdir failed: ", strerror(errno));
1095: return -1;
1096: }
1097: }
1098: #endif
1099: #ifdef HAVE_PWD_H
1100: /* drop root privs */
1101: if (NULL != pwd) {
1.1.1.2 misho 1102: if (-1 == setuid(pwd->pw_uid)) {
1103: log_error_write(srv, __FILE__, __LINE__, "ss", "setuid failed: ", strerror(errno));
1104: return -1;
1105: }
1.1 misho 1106: }
1107: #endif
1108: #if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
1109: /**
1110: * on IRIX 6.5.30 they have prctl() but no DUMPABLE
1111: */
1112: if (srv->srvconf.enable_cores) {
1113: prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
1114: }
1115: #endif
1116: } else {
1117:
1118: #ifdef HAVE_GETRLIMIT
1119: if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
1120: log_error_write(srv, __FILE__, __LINE__,
1121: "ss", "couldn't get 'max filedescriptors'",
1122: strerror(errno));
1123: return -1;
1124: }
1125:
1126: /**
1.1.1.3 ! misho 1127: * we are not root can can't increase the fd-limit above rlim_max, but we can reduce it
1.1 misho 1128: */
1.1.1.3 ! misho 1129: if (srv->srvconf.max_fds && srv->srvconf.max_fds <= rlim.rlim_max) {
1.1 misho 1130: /* set rlimits */
1131:
1132: rlim.rlim_cur = srv->srvconf.max_fds;
1133:
1134: if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
1135: log_error_write(srv, __FILE__, __LINE__,
1136: "ss", "couldn't set 'max filedescriptors'",
1137: strerror(errno));
1138: return -1;
1139: }
1140: }
1141:
1142: if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
1.1.1.3 ! misho 1143: srv->max_fds = rlim.rlim_cur < (rlim_t)FD_SETSIZE - 200 ? (int)rlim.rlim_cur : (int)FD_SETSIZE - 200;
1.1 misho 1144: } else {
1145: srv->max_fds = rlim.rlim_cur;
1146: }
1147:
1148: /* set core file rlimit, if enable_cores is set */
1149: if (srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
1150: rlim.rlim_cur = rlim.rlim_max;
1151: setrlimit(RLIMIT_CORE, &rlim);
1152: }
1153:
1154: #endif
1155: if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
1156: /* don't raise the limit above FD_SET_SIZE */
1157: if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
1158: log_error_write(srv, __FILE__, __LINE__, "sd",
1159: "can't raise max filedescriptors above", FD_SETSIZE - 200,
1160: "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
1161: return -1;
1162: }
1163: }
1164:
1165: if (0 != network_init(srv)) {
1166: plugins_free(srv);
1167: server_free(srv);
1168:
1169: return -1;
1170: }
1171: }
1172:
1173: /* set max-conns */
1174: if (srv->srvconf.max_conns > srv->max_fds/2) {
1175: /* we can't have more connections than max-fds/2 */
1176: log_error_write(srv, __FILE__, __LINE__, "sdd", "can't have more connections than fds/2: ", srv->srvconf.max_conns, srv->max_fds);
1177: srv->max_conns = srv->max_fds/2;
1178: } else if (srv->srvconf.max_conns) {
1179: /* otherwise respect the wishes of the user */
1180: srv->max_conns = srv->srvconf.max_conns;
1181: } else {
1182: /* or use the default: we really don't want to hit max-fds */
1183: srv->max_conns = srv->max_fds/3;
1184: }
1185:
1186: if (HANDLER_GO_ON != plugins_call_init(srv)) {
1187: log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
1188:
1189: plugins_free(srv);
1190: network_close(srv);
1191: server_free(srv);
1192:
1193: return -1;
1194: }
1195:
1196: #ifdef HAVE_FORK
1197: /* network is up, let's deamonize ourself */
1.1.1.3 ! misho 1198: if (srv->srvconf.dont_daemonize == 0) {
! 1199: parent_pipe_fd = daemonize();
! 1200: }
1.1 misho 1201: #endif
1202:
1203:
1204: #ifdef HAVE_SIGACTION
1205: memset(&act, 0, sizeof(act));
1206: act.sa_handler = SIG_IGN;
1207: sigaction(SIGPIPE, &act, NULL);
1208: sigaction(SIGUSR1, &act, NULL);
1209: # if defined(SA_SIGINFO)
1210: act.sa_sigaction = sigaction_handler;
1211: sigemptyset(&act.sa_mask);
1212: act.sa_flags = SA_SIGINFO;
1213: # else
1214: act.sa_handler = signal_handler;
1215: sigemptyset(&act.sa_mask);
1216: act.sa_flags = 0;
1217: # endif
1218: sigaction(SIGINT, &act, NULL);
1219: sigaction(SIGTERM, &act, NULL);
1220: sigaction(SIGHUP, &act, NULL);
1221: sigaction(SIGALRM, &act, NULL);
1.1.1.3 ! misho 1222:
! 1223: /* it should be safe to restart syscalls after SIGCHLD */
! 1224: act.sa_flags |= SA_RESTART | SA_NOCLDSTOP;
1.1 misho 1225: sigaction(SIGCHLD, &act, NULL);
1226:
1227: #elif defined(HAVE_SIGNAL)
1228: /* ignore the SIGPIPE from sendfile() */
1229: signal(SIGPIPE, SIG_IGN);
1230: signal(SIGUSR1, SIG_IGN);
1231: signal(SIGALRM, signal_handler);
1232: signal(SIGTERM, signal_handler);
1233: signal(SIGHUP, signal_handler);
1234: signal(SIGCHLD, signal_handler);
1235: signal(SIGINT, signal_handler);
1236: #endif
1237:
1238: #ifdef USE_ALARM
1239: signal(SIGALRM, signal_handler);
1240:
1241: /* setup periodic timer (1 second) */
1242: if (setitimer(ITIMER_REAL, &interval, NULL)) {
1243: log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
1244: return -1;
1245: }
1246:
1247: getitimer(ITIMER_REAL, &interval);
1248: #endif
1249:
1250:
1251: srv->gid = getgid();
1252: srv->uid = getuid();
1253:
1254: /* write pid file */
1255: if (pid_fd != -1) {
1.1.1.3 ! misho 1256: buffer_copy_int(srv->tmp_buf, getpid());
1.1 misho 1257: buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n"));
1.1.1.3 ! misho 1258: if (-1 == write_all(pid_fd, CONST_BUF_LEN(srv->tmp_buf))) {
! 1259: log_error_write(srv, __FILE__, __LINE__, "ss", "Couldn't write pid file:", strerror(errno));
! 1260: close(pid_fd);
! 1261: return -1;
! 1262: }
1.1 misho 1263: }
1264:
1265: /* Close stderr ASAP in the child process to make sure that nothing
1266: * is being written to that fd which may not be valid anymore. */
1.1.1.3 ! misho 1267: if (!srv->srvconf.preflight_check && -1 == log_error_open(srv)) {
1.1 misho 1268: log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");
1269:
1270: plugins_free(srv);
1271: network_close(srv);
1272: server_free(srv);
1273: return -1;
1274: }
1275:
1276: if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
1277: log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
1278:
1279: plugins_free(srv);
1280: network_close(srv);
1281: server_free(srv);
1282:
1283: return -1;
1284: }
1285:
1.1.1.3 ! misho 1286: /* settings might be enabled during module config set defaults */
! 1287: srv->config_storage[0]->high_precision_timestamps = srv->srvconf.high_precision_timestamps;
! 1288:
1.1 misho 1289: /* dump unused config-keys */
1290: for (i = 0; i < srv->config_context->used; i++) {
1291: array *config = ((data_config *)srv->config_context->data[i])->value;
1292: size_t j;
1293:
1294: for (j = 0; config && j < config->used; j++) {
1295: data_unset *du = config->data[j];
1296:
1297: /* all var.* is known as user defined variable */
1298: if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
1299: continue;
1300: }
1301:
1302: if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
1303: log_error_write(srv, __FILE__, __LINE__, "sbs",
1304: "WARNING: unknown config-key:",
1305: du->key,
1306: "(ignored)");
1307: }
1308: }
1309: }
1310:
1311: if (srv->config_unsupported) {
1312: log_error_write(srv, __FILE__, __LINE__, "s",
1313: "Configuration contains unsupported keys. Going down.");
1314: }
1315:
1316: if (srv->config_deprecated) {
1317: log_error_write(srv, __FILE__, __LINE__, "s",
1318: "Configuration contains deprecated keys. Going down.");
1319: }
1320:
1321: if (srv->config_unsupported || srv->config_deprecated) {
1322: plugins_free(srv);
1323: network_close(srv);
1324: server_free(srv);
1325:
1326: return -1;
1327: }
1328:
1.1.1.3 ! misho 1329: if (srv->srvconf.preflight_check) {
! 1330: /*printf("Preflight OK");*//*(stdout reopened to /dev/null)*/
! 1331: plugins_free(srv);
! 1332: network_close(srv);
! 1333: server_free(srv);
! 1334:
! 1335: exit(0);
! 1336: }
! 1337:
1.1 misho 1338:
1339: #ifdef HAVE_FORK
1.1.1.3 ! misho 1340: /**
! 1341: * notify daemonize-grandparent of successful startup
! 1342: * do this before any further forking is done (workers)
! 1343: */
! 1344: if (srv->srvconf.dont_daemonize == 0) {
! 1345: if (0 > write(parent_pipe_fd, "", 1)) return -1;
! 1346: close(parent_pipe_fd);
! 1347: }
! 1348:
! 1349: if (idle_limit && srv->srvconf.max_worker) {
! 1350: srv->srvconf.max_worker = 0;
! 1351: log_error_write(srv, __FILE__, __LINE__, "s",
! 1352: "server idle time limit command line option disables server.max-worker config file option.");
! 1353: }
! 1354:
1.1 misho 1355: /* start watcher and workers */
1356: num_childs = srv->srvconf.max_worker;
1357: if (num_childs > 0) {
1358: int child = 0;
1359: while (!child && !srv_shutdown && !graceful_shutdown) {
1360: if (num_childs > 0) {
1361: switch (fork()) {
1362: case -1:
1363: return -1;
1364: case 0:
1365: child = 1;
1366: break;
1367: default:
1368: num_childs--;
1369: break;
1370: }
1371: } else {
1372: int status;
1373:
1374: if (-1 != wait(&status)) {
1375: /**
1376: * one of our workers went away
1377: */
1378: num_childs++;
1379: } else {
1380: switch (errno) {
1381: case EINTR:
1382: /**
1383: * if we receive a SIGHUP we have to close our logs ourself as we don't
1384: * have the mainloop who can help us here
1385: */
1386: if (handle_sig_hup) {
1387: handle_sig_hup = 0;
1388:
1389: log_error_cycle(srv);
1390:
1391: /**
1392: * forward to all procs in the process-group
1393: *
1394: * we also send it ourself
1395: */
1.1.1.3 ! misho 1396: if (!forwarded_sig_hup && 0 != srv->srvconf.max_worker) {
1.1 misho 1397: forwarded_sig_hup = 1;
1398: kill(0, SIGHUP);
1399: }
1400: }
1401: break;
1402: default:
1403: break;
1404: }
1405: }
1406: }
1407: }
1408:
1409: /**
1410: * for the parent this is the exit-point
1411: */
1412: if (!child) {
1413: /**
1414: * kill all children too
1415: */
1416: if (graceful_shutdown) {
1417: kill(0, SIGINT);
1418: } else if (srv_shutdown) {
1419: kill(0, SIGTERM);
1420: }
1421:
1.1.1.3 ! misho 1422: remove_pid_file(srv, &pid_fd);
1.1 misho 1423: log_error_close(srv);
1424: network_close(srv);
1425: connections_free(srv);
1426: plugins_free(srv);
1427: server_free(srv);
1428: return 0;
1429: }
1.1.1.3 ! misho 1430:
! 1431: /**
! 1432: * make sure workers do not muck with pid-file
! 1433: */
! 1434: if (0 <= pid_fd) {
! 1435: close(pid_fd);
! 1436: pid_fd = -1;
! 1437: }
! 1438: buffer_reset(srv->srvconf.pid_file);
1.1 misho 1439: }
1440: #endif
1441:
1442: if (NULL == (srv->ev = fdevent_init(srv, srv->max_fds + 1, srv->event_handler))) {
1443: log_error_write(srv, __FILE__, __LINE__,
1444: "s", "fdevent_init failed");
1445: return -1;
1446: }
1447:
1448: /* libev backend overwrites our SIGCHLD handler and calls waitpid on SIGCHLD; we want our own SIGCHLD handling. */
1449: #ifdef HAVE_SIGACTION
1450: sigaction(SIGCHLD, &act, NULL);
1451: #elif defined(HAVE_SIGNAL)
1452: signal(SIGCHLD, signal_handler);
1453: #endif
1454:
1455: /*
1456: * kqueue() is called here, select resets its internals,
1457: * all server sockets get their handlers
1458: *
1459: * */
1460: if (0 != network_register_fdevents(srv)) {
1461: plugins_free(srv);
1462: network_close(srv);
1463: server_free(srv);
1464:
1465: return -1;
1466: }
1467:
1468: /* might fail if user is using fam (not gamin) and famd isn't running */
1469: if (NULL == (srv->stat_cache = stat_cache_init())) {
1470: log_error_write(srv, __FILE__, __LINE__, "s",
1471: "stat-cache could not be setup, dieing.");
1472: return -1;
1473: }
1474:
1475: #ifdef HAVE_FAM_H
1476: /* setup FAM */
1477: if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
1.1.1.2 misho 1478: if (0 != FAMOpen2(&srv->stat_cache->fam, "lighttpd")) {
1.1 misho 1479: log_error_write(srv, __FILE__, __LINE__, "s",
1480: "could not open a fam connection, dieing.");
1481: return -1;
1482: }
1483: #ifdef HAVE_FAMNOEXISTS
1.1.1.2 misho 1484: FAMNoExists(&srv->stat_cache->fam);
1.1 misho 1485: #endif
1486:
1.1.1.2 misho 1487: fdevent_register(srv->ev, FAMCONNECTION_GETFD(&srv->stat_cache->fam), stat_cache_handle_fdevent, NULL);
1488: fdevent_event_set(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(&srv->stat_cache->fam), FDEVENT_IN);
1.1 misho 1489: }
1490: #endif
1491:
1492:
1493: /* get the current number of FDs */
1494: srv->cur_fds = open("/dev/null", O_RDONLY);
1495: close(srv->cur_fds);
1496:
1497: for (i = 0; i < srv->srv_sockets.used; i++) {
1498: server_socket *srv_socket = srv->srv_sockets.ptr[i];
1.1.1.3 ! misho 1499: if (srv->sockets_disabled) continue; /* lighttpd -1 (one-shot mode) */
1.1 misho 1500: if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) {
1501: log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));
1502: return -1;
1503: }
1504: }
1505:
1.1.1.3 ! misho 1506: if (oneshot_fd && server_oneshot_init(srv, oneshot_fd)) {
! 1507: oneshot_fd = -1;
! 1508: }
! 1509:
1.1 misho 1510: /* main-loop */
1511: while (!srv_shutdown) {
1512: int n;
1513: size_t ndx;
1514: time_t min_ts;
1515:
1516: if (handle_sig_hup) {
1517: handler_t r;
1518:
1519: /* reset notification */
1520: handle_sig_hup = 0;
1521:
1522:
1523: /* cycle logfiles */
1524:
1525: switch(r = plugins_call_handle_sighup(srv)) {
1526: case HANDLER_GO_ON:
1527: break;
1528: default:
1529: log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
1530: break;
1531: }
1532:
1533: if (-1 == log_error_cycle(srv)) {
1534: log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
1535:
1536: return -1;
1537: } else {
1538: #ifdef HAVE_SIGACTION
1539: log_error_write(srv, __FILE__, __LINE__, "sdsd",
1540: "logfiles cycled UID =",
1541: last_sighup_info.si_uid,
1542: "PID =",
1543: last_sighup_info.si_pid);
1544: #else
1545: log_error_write(srv, __FILE__, __LINE__, "s",
1546: "logfiles cycled");
1547: #endif
1548: }
1549: }
1550:
1551: if (handle_sig_alarm) {
1552: /* a new second */
1553:
1554: #ifdef USE_ALARM
1555: /* reset notification */
1556: handle_sig_alarm = 0;
1557: #endif
1558:
1559: /* get current time */
1560: min_ts = time(NULL);
1561:
1562: if (min_ts != srv->cur_ts) {
1.1.1.3 ! misho 1563: #ifdef DEBUG_CONNECTION_STATES
1.1 misho 1564: int cs = 0;
1.1.1.3 ! misho 1565: #endif
1.1 misho 1566: connections *conns = srv->conns;
1567: handler_t r;
1568:
1569: switch(r = plugins_call_handle_trigger(srv)) {
1570: case HANDLER_GO_ON:
1571: break;
1572: case HANDLER_ERROR:
1573: log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
1574: break;
1575: default:
1576: log_error_write(srv, __FILE__, __LINE__, "d", r);
1577: break;
1578: }
1579:
1580: /* trigger waitpid */
1581: srv->cur_ts = min_ts;
1582:
1.1.1.3 ! misho 1583: /* check idle time limit, if enabled */
! 1584: if (idle_limit && idle_limit < min_ts - last_active_ts && !graceful_shutdown) {
! 1585: log_error_write(srv, __FILE__, __LINE__, "sDs", "[note] idle timeout", (int)idle_limit,
! 1586: "s exceeded, initiating graceful shutdown");
! 1587: graceful_shutdown = 2; /* value 2 indicates idle timeout */
! 1588: }
! 1589:
1.1 misho 1590: /* cleanup stat-cache */
1591: stat_cache_trigger_cleanup(srv);
1592: /**
1593: * check all connections for timeouts
1594: *
1595: */
1596: for (ndx = 0; ndx < conns->used; ndx++) {
1.1.1.3 ! misho 1597: connection * const con = conns->ptr[ndx];
! 1598: const int waitevents = fdevent_event_get_interest(srv->ev, con->fd);
1.1 misho 1599: int changed = 0;
1600: int t_diff;
1601:
1.1.1.3 ! misho 1602: if (con->state == CON_STATE_CLOSE) {
! 1603: if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
! 1604: changed = 1;
! 1605: }
! 1606: } else if (waitevents & FDEVENT_IN) {
! 1607: if (con->request_count == 1 || con->state != CON_STATE_READ) { /* e.g. CON_STATE_READ_POST || CON_STATE_WRITE */
1.1 misho 1608: if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
1609: /* time - out */
1.1.1.3 ! misho 1610: if (con->conf.log_request_handling) {
! 1611: log_error_write(srv, __FILE__, __LINE__, "sd",
! 1612: "connection closed - read timeout:", con->fd);
! 1613: }
! 1614:
1.1 misho 1615: connection_set_state(srv, con, CON_STATE_ERROR);
1616: changed = 1;
1617: }
1618: } else {
1619: if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {
1620: /* time - out */
1.1.1.3 ! misho 1621: if (con->conf.log_request_handling) {
! 1622: log_error_write(srv, __FILE__, __LINE__, "sd",
! 1623: "connection closed - keep-alive timeout:", con->fd);
! 1624: }
! 1625:
1.1 misho 1626: connection_set_state(srv, con, CON_STATE_ERROR);
1627: changed = 1;
1628: }
1629: }
1630: }
1631:
1.1.1.3 ! misho 1632: /* max_write_idle timeout currently functions as backend timeout,
! 1633: * too, after response has been started.
! 1634: * future: have separate backend timeout, and then change this
! 1635: * to check for write interest before checking for timeout */
! 1636: /*if (waitevents & FDEVENT_OUT)*/
1.1 misho 1637: if ((con->state == CON_STATE_WRITE) &&
1638: (con->write_request_ts != 0)) {
1639: #if 0
1640: if (srv->cur_ts - con->write_request_ts > 60) {
1641: log_error_write(srv, __FILE__, __LINE__, "sdd",
1642: "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
1643: }
1644: #endif
1645:
1646: if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
1647: /* time - out */
1648: if (con->conf.log_timeouts) {
1.1.1.3 ! misho 1649: log_error_write(srv, __FILE__, __LINE__, "sbsbsosds",
! 1650: "NOTE: a request from",
! 1651: con->dst_addr_buf,
! 1652: "for",
1.1 misho 1653: con->request.uri,
1654: "timed out after writing",
1655: con->bytes_written,
1656: "bytes. We waited",
1657: (int)con->conf.max_write_idle,
1658: "seconds. If this a problem increase server.max-write-idle");
1659: }
1660: connection_set_state(srv, con, CON_STATE_ERROR);
1661: changed = 1;
1662: }
1663: }
1664:
1665: /* we don't like div by zero */
1666: if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
1667:
1668: if (con->traffic_limit_reached &&
1669: (con->conf.kbytes_per_second == 0 ||
1670: ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
1671: /* enable connection again */
1672: con->traffic_limit_reached = 0;
1673:
1674: changed = 1;
1675: }
1676:
1677: if (changed) {
1678: connection_state_machine(srv, con);
1679: }
1680: con->bytes_written_cur_second = 0;
1681: *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
1682:
1.1.1.3 ! misho 1683: #if DEBUG_CONNECTION_STATES
1.1 misho 1684: if (cs == 0) {
1685: fprintf(stderr, "connection-state: ");
1686: cs = 1;
1687: }
1688:
1689: fprintf(stderr, "c[%d,%d]: %s ",
1690: con->fd,
1691: con->fcgi.fd,
1692: connection_get_state(con->state));
1693: #endif
1694: }
1695:
1.1.1.3 ! misho 1696: #ifdef DEBUG_CONNECTION_STATES
1.1 misho 1697: if (cs == 1) fprintf(stderr, "\n");
1.1.1.3 ! misho 1698: #endif
1.1 misho 1699: }
1700: }
1701:
1702: if (srv->sockets_disabled) {
1703: /* our server sockets are disabled, why ? */
1704:
1705: if ((srv->cur_fds + srv->want_fds < srv->max_fds * 8 / 10) && /* we have enough unused fds */
1706: (srv->conns->used <= srv->max_conns * 9 / 10) &&
1707: (0 == graceful_shutdown)) {
1708: for (i = 0; i < srv->srv_sockets.used; i++) {
1709: server_socket *srv_socket = srv->srv_sockets.ptr[i];
1710: fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
1711: }
1712:
1713: log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
1714:
1715: srv->sockets_disabled = 0;
1716: }
1717: } else {
1718: if ((srv->cur_fds + srv->want_fds > srv->max_fds * 9 / 10) || /* out of fds */
1719: (srv->conns->used >= srv->max_conns) || /* out of connections */
1720: (graceful_shutdown)) { /* graceful_shutdown */
1721:
1722: /* disable server-fds */
1723:
1724: for (i = 0; i < srv->srv_sockets.used; i++) {
1725: server_socket *srv_socket = srv->srv_sockets.ptr[i];
1726:
1727: if (graceful_shutdown) {
1728: /* we don't want this socket anymore,
1729: *
1730: * closing it right away will make it possible for
1731: * the next lighttpd to take over (graceful restart)
1732: * */
1733:
1.1.1.3 ! misho 1734: fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
1.1 misho 1735: fdevent_unregister(srv->ev, srv_socket->fd);
1736: close(srv_socket->fd);
1737: srv_socket->fd = -1;
1738:
1739: /* network_close() will cleanup after us */
1.1.1.3 ! misho 1740: } else {
! 1741: fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, 0);
1.1 misho 1742: }
1743: }
1744:
1745: if (graceful_shutdown) {
1.1.1.3 ! misho 1746: remove_pid_file(srv, &pid_fd);
1.1 misho 1747: log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
1748: } else if (srv->conns->used >= srv->max_conns) {
1749: log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
1750: } else {
1751: log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
1752: }
1753:
1754: srv->sockets_disabled = 1;
1755: }
1756: }
1757:
1758: if (graceful_shutdown && srv->conns->used == 0) {
1759: /* we are in graceful shutdown phase and all connections are closed
1760: * we are ready to terminate without harming anyone */
1761: srv_shutdown = 1;
1.1.1.3 ! misho 1762: break;
1.1 misho 1763: }
1764:
1765: /* we still have some fds to share */
1766: if (srv->want_fds) {
1767: /* check the fdwaitqueue for waiting fds */
1768: int free_fds = srv->max_fds - srv->cur_fds - 16;
1769: connection *con;
1770:
1771: for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
1772: connection_state_machine(srv, con);
1773:
1774: srv->want_fds--;
1775: }
1776: }
1777:
1778: if ((n = fdevent_poll(srv->ev, 1000)) > 0) {
1779: /* n is the number of events */
1780: int revents;
1781: int fd_ndx;
1.1.1.3 ! misho 1782: last_active_ts = srv->cur_ts;
1.1 misho 1783: fd_ndx = -1;
1784: do {
1785: fdevent_handler handler;
1786: void *context;
1787:
1788: fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx);
1789: if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */
1790:
1791: revents = fdevent_event_get_revent (srv->ev, fd_ndx);
1792: fd = fdevent_event_get_fd (srv->ev, fd_ndx);
1793: handler = fdevent_get_handler(srv->ev, fd);
1794: context = fdevent_get_context(srv->ev, fd);
1.1.1.3 ! misho 1795: (*handler)(srv, context, revents);
1.1 misho 1796: } while (--n > 0);
1797: } else if (n < 0 && errno != EINTR) {
1798: log_error_write(srv, __FILE__, __LINE__, "ss",
1799: "fdevent_poll failed:",
1800: strerror(errno));
1801: }
1802:
1803: for (ndx = 0; ndx < srv->joblist->used; ndx++) {
1804: connection *con = srv->joblist->ptr[ndx];
1805: connection_state_machine(srv, con);
1806: con->in_joblist = 0;
1807: }
1808:
1809: srv->joblist->used = 0;
1810: }
1811:
1.1.1.3 ! misho 1812: if (0 == graceful_shutdown) {
! 1813: remove_pid_file(srv, &pid_fd);
1.1 misho 1814: }
1815:
1.1.1.3 ! misho 1816: if (2 == graceful_shutdown) { /* value 2 indicates idle timeout */
! 1817: log_error_write(srv, __FILE__, __LINE__, "s",
! 1818: "server stopped after idle timeout");
! 1819: } else {
1.1 misho 1820: #ifdef HAVE_SIGACTION
1.1.1.3 ! misho 1821: log_error_write(srv, __FILE__, __LINE__, "sdsd",
! 1822: "server stopped by UID =",
! 1823: last_sigterm_info.si_uid,
! 1824: "PID =",
! 1825: last_sigterm_info.si_pid);
1.1 misho 1826: #else
1.1.1.3 ! misho 1827: log_error_write(srv, __FILE__, __LINE__, "s",
! 1828: "server stopped");
1.1 misho 1829: #endif
1.1.1.3 ! misho 1830: }
1.1 misho 1831:
1832: /* clean-up */
1833: log_error_close(srv);
1834: network_close(srv);
1835: connections_free(srv);
1836: plugins_free(srv);
1837: server_free(srv);
1838:
1839: return 0;
1840: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>