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