Mercurial > hg > nginx
comparison src/core/nginx.c @ 219:f57597ec5249
nginx-0.0.1-2004-01-06-19:49:34 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 06 Jan 2004 16:49:34 +0000 |
parents | 05592fd7a436 |
children | 4f81b931e9ff |
comparison
equal
deleted
inserted
replaced
218:05592fd7a436 | 219:f57597ec5249 |
---|---|
4 #include <ngx_event.h> | 4 #include <ngx_event.h> |
5 #include <nginx.h> | 5 #include <nginx.h> |
6 | 6 |
7 | 7 |
8 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); | 8 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); |
9 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp); | |
9 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); | 10 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); |
10 static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle); | 11 static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle); |
11 | 12 |
12 | 13 |
13 typedef struct { | 14 typedef struct { |
124 | 125 |
125 if (!(init_cycle.pool = ngx_create_pool(1024, log))) { | 126 if (!(init_cycle.pool = ngx_create_pool(1024, log))) { |
126 return 1; | 127 return 1; |
127 } | 128 } |
128 | 129 |
129 if (ngx_set_inherited_sockets(&init_cycle, envp) == NGX_ERROR) { | 130 if (ngx_add_inherited_sockets(&init_cycle, envp) == NGX_ERROR) { |
130 return 1; | 131 return 1; |
131 } | 132 } |
132 | 133 |
133 cycle = ngx_init_cycle(&init_cycle); | 134 cycle = ngx_init_cycle(&init_cycle); |
134 if (cycle == NULL) { | 135 if (cycle == NULL) { |
325 break; | 326 break; |
326 } | 327 } |
327 } | 328 } |
328 } | 329 } |
329 | 330 |
330 #if 0 | 331 |
331 | 332 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) |
332 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) | |
333 { | 333 { |
334 ngx_int_t i, n, failed; | 334 ngx_int_t i; |
335 ngx_str_t conf_file; | 335 ngx_listening_t *ls; |
336 ngx_log_t *log; | 336 |
337 ngx_conf_t conf; | 337 if (user) { |
338 ngx_pool_t *pool; | 338 if (setuid(user) == -1) { |
339 ngx_cycle_t *cycle, **old; | 339 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
340 ngx_socket_t fd; | 340 "setuid() failed"); |
341 ngx_core_conf_t *ccf; | 341 /* fatal */ |
342 ngx_open_file_t *file; | 342 exit(1); |
343 ngx_listening_t *ls, *nls; | 343 } |
344 | 344 } |
345 log = old_cycle->log; | 345 |
346 | 346 ngx_init_temp_number(); |
347 if (!(pool = ngx_create_pool(16 * 1024, log))) { | 347 |
348 return NULL; | 348 /* |
349 } | 349 * disable deleting previous events for the listening sockets because |
350 | 350 * in the worker processes there are no events at all at this point |
351 if (!(cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)))) { | 351 */ |
352 ngx_destroy_pool(pool); | 352 ls = cycle->listening.elts; |
353 return NULL; | 353 for (i = 0; i < cycle->listening.nelts; i++) { |
354 } | 354 ls[i].remain = 0; |
355 cycle->pool = pool; | 355 } |
356 | |
357 cycle->old_cycle = old_cycle; | |
358 | |
359 | |
360 n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10; | |
361 if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) { | |
362 ngx_destroy_pool(pool); | |
363 return NULL; | |
364 } | |
365 cycle->pathes.nelts = 0; | |
366 cycle->pathes.size = sizeof(ngx_path_t *); | |
367 cycle->pathes.nalloc = n; | |
368 cycle->pathes.pool = pool; | |
369 | |
370 | |
371 n = old_cycle->open_files.nelts ? old_cycle->open_files.nelts : 20; | |
372 cycle->open_files.elts = ngx_pcalloc(pool, n * sizeof(ngx_open_file_t)); | |
373 if (cycle->open_files.elts == NULL) { | |
374 ngx_destroy_pool(pool); | |
375 return NULL; | |
376 } | |
377 cycle->open_files.nelts = 0; | |
378 cycle->open_files.size = sizeof(ngx_open_file_t); | |
379 cycle->open_files.nalloc = n; | |
380 cycle->open_files.pool = pool; | |
381 | |
382 | |
383 if (!(cycle->log = ngx_log_create_errlog(cycle, NULL))) { | |
384 ngx_destroy_pool(pool); | |
385 return NULL; | |
386 } | |
387 | |
388 | |
389 n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; | |
390 cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); | |
391 if (cycle->listening.elts == NULL) { | |
392 ngx_destroy_pool(pool); | |
393 return NULL; | |
394 } | |
395 cycle->listening.nelts = 0; | |
396 cycle->listening.size = sizeof(ngx_listening_t); | |
397 cycle->listening.nalloc = n; | |
398 cycle->listening.pool = pool; | |
399 | |
400 | |
401 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); | |
402 if (cycle->conf_ctx == NULL) { | |
403 ngx_destroy_pool(pool); | |
404 return NULL; | |
405 } | |
406 | |
407 | |
408 if (!(ccf = ngx_pcalloc(pool, sizeof(ngx_core_conf_t)))) { | |
409 ngx_destroy_pool(pool); | |
410 return NULL; | |
411 } | |
412 /* set by pcalloc() | |
413 * | |
414 * ccf->pid = NULL; | |
415 */ | |
416 ccf->daemon = -1; | |
417 ccf->single = -1; | |
418 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf; | |
419 | |
420 | |
421 ngx_memzero(&conf, sizeof(ngx_conf_t)); | |
422 /* STUB: init array ? */ | |
423 conf.args = ngx_create_array(pool, 10, sizeof(ngx_str_t)); | |
424 if (conf.args == NULL) { | |
425 ngx_destroy_pool(pool); | |
426 return NULL; | |
427 } | |
428 | |
429 conf.ctx = cycle->conf_ctx; | |
430 conf.cycle = cycle; | |
431 /* STUB */ conf.pool = cycle->pool; | |
432 conf.log = log; | |
433 conf.module_type = NGX_CORE_MODULE; | |
434 conf.cmd_type = NGX_MAIN_CONF; | |
435 | |
436 conf_file.len = sizeof(NGINX_CONF) - 1; | |
437 conf_file.data = NGINX_CONF; | |
438 | |
439 if (ngx_conf_parse(&conf, &conf_file) != NGX_CONF_OK) { | |
440 ngx_destroy_pool(pool); | |
441 return NULL; | |
442 } | |
443 | |
444 | |
445 failed = 0; | |
446 | |
447 file = cycle->open_files.elts; | |
448 for (i = 0; i < cycle->open_files.nelts; i++) { | |
449 if (file[i].name.data == NULL) { | |
450 continue; | |
451 } | |
452 | |
453 file[i].fd = ngx_open_file(file[i].name.data, | |
454 NGX_FILE_RDWR, | |
455 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); | |
456 | |
457 ngx_log_debug(log, "OPEN: %d:%s" _ file[i].fd _ file[i].name.data); | |
458 | |
459 if (file[i].fd == NGX_INVALID_FILE) { | |
460 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, | |
461 ngx_open_file_n " \"%s\" failed", | |
462 file[i].name.data); | |
463 failed = 1; | |
464 break; | |
465 } | |
466 | |
467 #if (WIN32) | |
468 if (ngx_file_append_mode(file[i].fd) == NGX_ERROR) { | |
469 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, | |
470 ngx_file_append_mode_n " \"%s\" failed", | |
471 file[i].name.data); | |
472 failed = 1; | |
473 break; | |
474 } | |
475 #endif | |
476 } | |
477 | |
478 if (!failed) { | |
479 if (old_cycle->listening.nelts) { | |
480 ls = old_cycle->listening.elts; | |
481 for (i = 0; i < old_cycle->listening.nelts; i++) { | |
482 ls[i].remain = 0; | |
483 } | |
484 | |
485 nls = cycle->listening.elts; | |
486 for (n = 0; n < cycle->listening.nelts; n++) { | |
487 for (i = 0; i < old_cycle->listening.nelts; i++) { | |
488 if (ls[i].ignore) { | |
489 continue; | |
490 } | |
491 | |
492 ngx_log_error(NGX_LOG_INFO, log, 0, | |
493 "%X, %X", | |
494 *(int *) ls[i].sockaddr, | |
495 *(int *) nls[n].sockaddr); | |
496 | |
497 if (ngx_memcmp(nls[n].sockaddr, | |
498 ls[i].sockaddr, ls[i].socklen) == 0) | |
499 { | |
500 fd = ls[i].fd; | |
501 #if (WIN32) | |
502 /* | |
503 * Winsock assignes a socket number divisible by 4 so | |
504 * to find a connection we divide a socket number by 4. | |
505 */ | |
506 | |
507 fd /= 4; | |
508 #endif | |
509 if (fd >= (ngx_socket_t) cycle->connection_n) { | |
510 ngx_log_error(NGX_LOG_EMERG, log, 0, | |
511 "%d connections is not enough to hold " | |
512 "an open listening socket on %s, " | |
513 "required at least %d connections", | |
514 cycle->connection_n, | |
515 ls[i].addr_text.data, fd); | |
516 failed = 1; | |
517 break; | |
518 } | |
519 | |
520 nls[n].fd = ls[i].fd; | |
521 nls[i].remain = 1; | |
522 ls[i].remain = 1; | |
523 break; | |
524 } | |
525 } | |
526 | |
527 if (nls[n].fd == -1) { | |
528 nls[n].new = 1; | |
529 } | |
530 } | |
531 | |
532 } else { | |
533 ls = cycle->listening.elts; | |
534 for (i = 0; i < cycle->listening.nelts; i++) { | |
535 ls[i].new = 1; | |
536 } | |
537 } | |
538 | |
539 if (!failed) { | |
540 if (ngx_open_listening_sockets(cycle) == NGX_ERROR) { | |
541 failed = 1; | |
542 } | |
543 } | |
544 } | |
545 | |
546 if (failed) { | |
547 | |
548 /* rollback the new cycle configuration */ | |
549 | |
550 file = cycle->open_files.elts; | |
551 for (i = 0; i < cycle->open_files.nelts; i++) { | |
552 if (file[i].fd == NGX_INVALID_FILE) { | |
553 continue; | |
554 } | |
555 | |
556 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { | |
557 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, | |
558 ngx_close_file_n " \"%s\" failed", | |
559 file[i].name.data); | |
560 } | |
561 } | |
562 | |
563 ls = cycle->listening.elts; | |
564 for (i = 0; i < cycle->listening.nelts; i++) { | |
565 if (ls[i].new && ls[i].fd == -1) { | |
566 continue; | |
567 } | |
568 | |
569 if (ngx_close_socket(ls[i].fd) == -1) { | |
570 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | |
571 ngx_close_socket_n " %s failed", | |
572 ls[i].addr_text.data); | |
573 } | |
574 } | |
575 | |
576 ngx_destroy_pool(pool); | |
577 return NULL; | |
578 } | |
579 | |
580 /* commit the new cycle configuration */ | |
581 | |
582 pool->log = cycle->log; | |
583 | |
584 | 356 |
585 for (i = 0; ngx_modules[i]; i++) { | 357 for (i = 0; ngx_modules[i]; i++) { |
586 if (ngx_modules[i]->init_module) { | 358 if (ngx_modules[i]->init_process) { |
587 if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) { | 359 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { |
588 /* fatal */ | 360 /* fatal */ |
589 exit(1); | 361 exit(1); |
590 } | 362 } |
591 } | 363 } |
592 } | 364 } |
593 | 365 |
594 /* close and delete stuff that lefts from an old cycle */ | 366 /* TODO: threads: start ngx_worker_thread_cycle() */ |
595 | 367 |
596 /* close the unneeded listening sockets */ | 368 for ( ;; ) { |
597 | 369 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); |
598 ls = old_cycle->listening.elts; | 370 |
599 for (i = 0; i < old_cycle->listening.nelts; i++) { | 371 ngx_process_events(cycle->log); |
600 if (ls[i].remain) { | 372 |
601 continue; | 373 if (ngx_terminate) { |
602 } | 374 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); |
603 | 375 exit(0); |
604 if (ngx_close_socket(ls[i].fd) == -1) { | 376 } |
605 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | 377 |
606 ngx_close_socket_n " %s failed", | 378 if (ngx_quit) { |
607 ls[i].addr_text.data); | 379 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, |
608 } | 380 "gracefully shutdowning"); |
609 } | 381 break; |
610 | 382 } |
611 | 383 |
612 /* close the unneeded open files */ | 384 if (ngx_reopen) { |
613 | 385 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); |
614 file = old_cycle->open_files.elts; | 386 ngx_reopen_files(cycle); |
615 for (i = 0; i < old_cycle->open_files.nelts; i++) { | 387 ngx_reopen = 0; |
616 if (file[i].fd == NGX_INVALID_FILE) { | 388 } |
617 continue; | 389 } |
618 } | 390 |
619 | 391 ngx_close_listening_sockets(cycle); |
620 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { | 392 |
621 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, | 393 for ( ;; ) { |
622 ngx_close_file_n " \"%s\" failed", | 394 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) { |
623 file[i].name.data); | 395 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); |
624 } | 396 exit(0); |
625 } | 397 } |
626 | 398 |
627 if (old_cycle->connections == NULL) { | 399 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); |
628 /* an old cycle is an init cycle */ | 400 |
629 ngx_destroy_pool(old_cycle->pool); | 401 ngx_process_events(cycle->log); |
630 return cycle; | 402 } |
631 } | |
632 | |
633 if (master) { | |
634 ngx_destroy_pool(old_cycle->pool); | |
635 return cycle; | |
636 } | |
637 | |
638 if (ngx_temp_pool == NULL) { | |
639 ngx_temp_pool = ngx_create_pool(128, cycle->log); | |
640 if (ngx_temp_pool == NULL) { | |
641 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, | |
642 "can not create ngx_temp_pool"); | |
643 exit(1); | |
644 } | |
645 | |
646 n = 10; | |
647 ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, | |
648 n * sizeof(ngx_cycle_t *)); | |
649 if (ngx_old_cycles.elts == NULL) { | |
650 exit(1); | |
651 } | |
652 ngx_old_cycles.nelts = 0; | |
653 ngx_old_cycles.size = sizeof(ngx_cycle_t *); | |
654 ngx_old_cycles.nalloc = n; | |
655 ngx_old_cycles.pool = ngx_temp_pool; | |
656 | |
657 ngx_cleaner_event.event_handler = ngx_clean_old_cycles; | |
658 ngx_cleaner_event.log = cycle->log; | |
659 ngx_cleaner_event.data = &dumb; | |
660 dumb.fd = (ngx_socket_t) -1; | |
661 } | |
662 | |
663 ngx_temp_pool->log = cycle->log; | |
664 | |
665 old = ngx_push_array(&ngx_old_cycles); | |
666 if (old == NULL) { | |
667 exit(1); | |
668 } | |
669 *old = old_cycle; | |
670 | |
671 if (!ngx_cleaner_event.timer_set) { | |
672 ngx_add_timer(&ngx_cleaner_event, 30000); | |
673 ngx_cleaner_event.timer_set = 1; | |
674 } | |
675 | |
676 return cycle; | |
677 } | 403 } |
678 | 404 |
679 #endif | 405 |
680 | 406 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp) |
681 | |
682 #if 0 | |
683 | |
684 static ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle, char **envp) | |
685 { | 407 { |
686 char *p, *v; | 408 char *p, *v; |
687 ngx_socket_t s; | 409 ngx_socket_t s; |
688 ngx_listening_t *ls; | 410 ngx_listening_t *ls; |
689 struct sockaddr_in *addr_in; | |
690 | 411 |
691 for ( /* void */ ; *envp; envp++) { | 412 for ( /* void */ ; *envp; envp++) { |
692 if (ngx_strncmp(*envp, NGINX_VAR, NGINX_VAR_LEN) != 0) { | 413 if (ngx_strncmp(*envp, NGINX_VAR, NGINX_VAR_LEN) != 0) { |
693 continue; | 414 continue; |
694 } | 415 } |
714 if (!(ls = ngx_push_array(&cycle->listening))) { | 435 if (!(ls = ngx_push_array(&cycle->listening))) { |
715 return NGX_ERROR; | 436 return NGX_ERROR; |
716 } | 437 } |
717 | 438 |
718 ls->fd = s; | 439 ls->fd = s; |
719 | |
720 /* AF_INET only */ | |
721 | |
722 ls->sockaddr = ngx_palloc(cycle->pool, | |
723 sizeof(struct sockaddr_in)); | |
724 if (ls->sockaddr == NULL) { | |
725 return NGX_ERROR; | |
726 } | |
727 | |
728 ls->socklen = sizeof(struct sockaddr_in); | |
729 if (getsockname(s, ls->sockaddr, &ls->socklen) == -1) { | |
730 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, | |
731 "getsockname() of the inherited " | |
732 "socket #%d failed", s); | |
733 ls->ignore = 1; | |
734 continue; | |
735 } | |
736 | |
737 addr_in = (struct sockaddr_in *) ls->sockaddr; | |
738 | |
739 if (addr_in->sin_family != AF_INET) { | |
740 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, | |
741 "the inherited socket #%d has " | |
742 "unsupported family", s); | |
743 ls->ignore = 1; | |
744 continue; | |
745 } | |
746 ls->addr_text_max_len = INET_ADDRSTRLEN; | |
747 | |
748 ls->addr_text.data = ngx_palloc(cycle->pool, | |
749 ls->addr_text_max_len); | |
750 if (ls->addr_text.data == NULL) { | |
751 return NGX_ERROR; | |
752 } | |
753 | |
754 addr_in->sin_len = 0; | |
755 | |
756 ls->family = addr_in->sin_family; | |
757 ls->addr_text.len = ngx_sock_ntop(ls->family, ls->sockaddr, | |
758 ls->addr_text.data, | |
759 ls->addr_text_max_len); | |
760 if (ls->addr_text.len == 0) { | |
761 return NGX_ERROR; | |
762 } | |
763 } | 440 } |
764 } | 441 } |
765 | 442 |
766 break; | 443 return ngx_set_inherited_sockets(cycle); |
767 } | 444 } |
768 | 445 |
769 return NGX_OK; | 446 return NGX_OK; |
770 } | |
771 | |
772 #endif | |
773 | |
774 | |
775 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) | |
776 { | |
777 ngx_int_t i; | |
778 ngx_listening_t *ls; | |
779 | |
780 if (user) { | |
781 if (setuid(user) == -1) { | |
782 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
783 "setuid() failed"); | |
784 /* fatal */ | |
785 exit(1); | |
786 } | |
787 } | |
788 | |
789 ngx_init_temp_number(); | |
790 | |
791 /* | |
792 * disable deleting previous events for the listening sockets because | |
793 * in the worker processes there are no events at all at this point | |
794 */ | |
795 ls = cycle->listening.elts; | |
796 for (i = 0; i < cycle->listening.nelts; i++) { | |
797 ls[i].remain = 0; | |
798 } | |
799 | |
800 for (i = 0; ngx_modules[i]; i++) { | |
801 if (ngx_modules[i]->init_process) { | |
802 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { | |
803 /* fatal */ | |
804 exit(1); | |
805 } | |
806 } | |
807 } | |
808 | |
809 /* TODO: threads: start ngx_worker_thread_cycle() */ | |
810 | |
811 for ( ;; ) { | |
812 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
813 | |
814 ngx_process_events(cycle->log); | |
815 | |
816 if (ngx_terminate) { | |
817 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
818 exit(0); | |
819 } | |
820 | |
821 if (ngx_quit) { | |
822 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
823 "gracefully shutdowning"); | |
824 break; | |
825 } | |
826 | |
827 if (ngx_reopen) { | |
828 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
829 ngx_reopen_files(cycle); | |
830 ngx_reopen = 0; | |
831 } | |
832 } | |
833 | |
834 ngx_close_listening_sockets(cycle); | |
835 | |
836 for ( ;; ) { | |
837 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) { | |
838 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
839 exit(0); | |
840 } | |
841 | |
842 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
843 | |
844 ngx_process_events(cycle->log); | |
845 } | |
846 } | 447 } |
847 | 448 |
848 | 449 |
849 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) | 450 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) |
850 { | 451 { |