Mercurial > hg > nginx
comparison src/os/unix/ngx_process_cycle.c @ 467:bbd6b0b4a2b1 release-0.1.8
nginx-0.1.8-RELEASE import
*) Bugfix: in the ngx_http_autoindex_module if the long file names were
in the listing.
*) Feature: the "^~" modifier in the location directive.
*) Feature: the proxy_max_temp_file_size directive.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 20 Nov 2004 19:52:20 +0000 |
parents | a88a3e4e158f |
children | 2ff194b74f1e |
comparison
equal
deleted
inserted
replaced
466:ee6d66462bff | 467:bbd6b0b4a2b1 |
---|---|
10 #include <ngx_channel.h> | 10 #include <ngx_channel.h> |
11 | 11 |
12 | 12 |
13 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, | 13 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, |
14 ngx_int_t type); | 14 ngx_int_t type); |
15 static void ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type); | |
15 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); | 16 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); |
16 static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle); | 17 static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle); |
17 static void ngx_master_exit(ngx_cycle_t *cycle); | 18 static void ngx_master_exit(ngx_cycle_t *cycle); |
18 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); | 19 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); |
20 static void ngx_worker_process_init(ngx_cycle_t *cycle); | |
19 static void ngx_channel_handler(ngx_event_t *ev); | 21 static void ngx_channel_handler(ngx_event_t *ev); |
20 #if (NGX_THREADS) | 22 #if (NGX_THREADS) |
21 static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle); | 23 static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle); |
22 static void *ngx_worker_thread_cycle(void *data); | 24 static void *ngx_worker_thread_cycle(void *data); |
23 #endif | 25 #endif |
26 static void ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data); | |
24 | 27 |
25 | 28 |
26 ngx_uint_t ngx_process; | 29 ngx_uint_t ngx_process; |
27 ngx_pid_t ngx_pid; | 30 ngx_pid_t ngx_pid; |
28 ngx_uint_t ngx_threaded; | 31 ngx_uint_t ngx_threaded; |
107 | 110 |
108 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); | 111 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); |
109 | 112 |
110 ngx_start_worker_processes(cycle, ccf->worker_processes, | 113 ngx_start_worker_processes(cycle, ccf->worker_processes, |
111 NGX_PROCESS_RESPAWN); | 114 NGX_PROCESS_RESPAWN); |
115 ngx_start_garbage_collector(cycle, NGX_PROCESS_RESPAWN); | |
112 | 116 |
113 ngx_new_binary = 0; | 117 ngx_new_binary = 0; |
114 delay = 0; | 118 delay = 0; |
115 live = 1; | 119 live = 1; |
116 | 120 |
177 ngx_timer = 0; | 181 ngx_timer = 0; |
178 | 182 |
179 if (!ngx_noaccepting) { | 183 if (!ngx_noaccepting) { |
180 ngx_start_worker_processes(cycle, ccf->worker_processes, | 184 ngx_start_worker_processes(cycle, ccf->worker_processes, |
181 NGX_PROCESS_JUST_RESPAWN); | 185 NGX_PROCESS_JUST_RESPAWN); |
186 ngx_start_garbage_collector(cycle, NGX_PROCESS_JUST_RESPAWN); | |
182 live = 1; | 187 live = 1; |
183 ngx_signal_worker_processes(cycle, | 188 ngx_signal_worker_processes(cycle, |
184 ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); | 189 ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); |
185 } | 190 } |
186 } | 191 } |
191 if (ngx_new_binary) { | 196 if (ngx_new_binary) { |
192 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "start new workers"); | 197 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "start new workers"); |
193 | 198 |
194 ngx_start_worker_processes(cycle, ccf->worker_processes, | 199 ngx_start_worker_processes(cycle, ccf->worker_processes, |
195 NGX_PROCESS_RESPAWN); | 200 NGX_PROCESS_RESPAWN); |
201 ngx_start_garbage_collector(cycle, NGX_PROCESS_RESPAWN); | |
196 ngx_noaccepting = 0; | 202 ngx_noaccepting = 0; |
197 | 203 |
198 continue; | 204 continue; |
199 } | 205 } |
200 | 206 |
209 ngx_cycle = cycle; | 215 ngx_cycle = cycle; |
210 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, | 216 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, |
211 ngx_core_module); | 217 ngx_core_module); |
212 ngx_start_worker_processes(cycle, ccf->worker_processes, | 218 ngx_start_worker_processes(cycle, ccf->worker_processes, |
213 NGX_PROCESS_JUST_RESPAWN); | 219 NGX_PROCESS_JUST_RESPAWN); |
220 ngx_start_garbage_collector(cycle, NGX_PROCESS_JUST_RESPAWN); | |
214 live = 1; | 221 live = 1; |
215 ngx_signal_worker_processes(cycle, | 222 ngx_signal_worker_processes(cycle, |
216 ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); | 223 ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); |
217 } | 224 } |
218 | 225 |
219 if (ngx_restart) { | 226 if (ngx_restart) { |
220 ngx_restart = 0; | 227 ngx_restart = 0; |
221 ngx_start_worker_processes(cycle, ccf->worker_processes, | 228 ngx_start_worker_processes(cycle, ccf->worker_processes, |
222 NGX_PROCESS_RESPAWN); | 229 NGX_PROCESS_RESPAWN); |
230 ngx_start_garbage_collector(cycle, NGX_PROCESS_RESPAWN); | |
223 live = 1; | 231 live = 1; |
224 } | 232 } |
225 | 233 |
226 if (ngx_reopen) { | 234 if (ngx_reopen) { |
227 ngx_reopen = 0; | 235 ngx_reopen = 0; |
346 itv.it_value.tv_usec = 0; | 354 itv.it_value.tv_usec = 0; |
347 | 355 |
348 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { | 356 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { |
349 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 357 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
350 "setitimer() failed"); | 358 "setitimer() failed"); |
359 } | |
360 } | |
361 | |
362 | |
363 static void ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type) | |
364 { | |
365 ngx_int_t i; | |
366 ngx_channel_t ch; | |
367 | |
368 return; | |
369 | |
370 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "start garbage collector"); | |
371 | |
372 ch.command = NGX_CMD_OPEN_CHANNEL; | |
373 | |
374 ngx_spawn_process(cycle, ngx_garbage_collector_cycle, NULL, | |
375 "garbage collector", type); | |
376 | |
377 ch.pid = ngx_processes[ngx_process_slot].pid; | |
378 ch.slot = ngx_process_slot; | |
379 ch.fd = ngx_processes[ngx_process_slot].channel[0]; | |
380 | |
381 for (i = 0; i < ngx_last_process; i++) { | |
382 | |
383 if (i == ngx_process_slot | |
384 || ngx_processes[i].pid == -1 | |
385 || ngx_processes[i].channel[0] == -1) | |
386 { | |
387 continue; | |
388 } | |
389 | |
390 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, | |
391 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", | |
392 ch.slot, ch.pid, ch.fd, | |
393 i, ngx_processes[i].pid, | |
394 ngx_processes[i].channel[0]); | |
395 | |
396 /* TODO: NGX_AGAIN */ | |
397 | |
398 ngx_write_channel(ngx_processes[i].channel[0], | |
399 &ch, sizeof(ngx_channel_t), cycle->log); | |
351 } | 400 } |
352 } | 401 } |
353 | 402 |
354 | 403 |
355 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo) | 404 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo) |
556 } | 605 } |
557 | 606 |
558 | 607 |
559 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) | 608 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) |
560 { | 609 { |
610 ngx_worker_process_init(cycle); | |
611 | |
612 ngx_setproctitle("worker process"); | |
613 | |
614 #if (NGX_THREADS) | |
615 | |
616 if (ngx_time_mutex_init(cycle->log) == NGX_ERROR) { | |
617 /* fatal */ | |
618 exit(2); | |
619 } | |
620 | |
621 if (ngx_threads_n) { | |
622 if (ngx_init_threads(ngx_threads_n, | |
623 ccf->thread_stack_size, cycle) == NGX_ERROR) | |
624 { | |
625 /* fatal */ | |
626 exit(2); | |
627 } | |
628 | |
629 err = ngx_thread_key_create(&ngx_core_tls_key); | |
630 if (err != 0) { | |
631 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, | |
632 ngx_thread_key_create_n " failed"); | |
633 /* fatal */ | |
634 exit(2); | |
635 } | |
636 | |
637 for (n = 0; n < ngx_threads_n; n++) { | |
638 | |
639 if (!(ngx_threads[n].cv = ngx_cond_init(cycle->log))) { | |
640 /* fatal */ | |
641 exit(2); | |
642 } | |
643 | |
644 if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid, | |
645 ngx_worker_thread_cycle, | |
646 (void *) &ngx_threads[n], cycle->log) != 0) | |
647 { | |
648 /* fatal */ | |
649 exit(2); | |
650 } | |
651 } | |
652 } | |
653 | |
654 #endif | |
655 | |
656 for ( ;; ) { | |
657 if (ngx_exiting | |
658 && ngx_event_timer_rbtree == &ngx_event_timer_sentinel) | |
659 { | |
660 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
661 | |
662 | |
663 #if (NGX_THREADS) | |
664 ngx_terminate = 1; | |
665 | |
666 ngx_wakeup_worker_threads(cycle); | |
667 #endif | |
668 | |
669 /* | |
670 * we do not destroy cycle->pool here because a signal handler | |
671 * that uses cycle->log can be called at this point | |
672 */ | |
673 exit(0); | |
674 } | |
675 | |
676 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
677 | |
678 ngx_process_events(cycle); | |
679 | |
680 if (ngx_terminate) { | |
681 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
682 | |
683 #if (NGX_THREADS) | |
684 ngx_wakeup_worker_threads(cycle); | |
685 #endif | |
686 | |
687 /* | |
688 * we do not destroy cycle->pool here because a signal handler | |
689 * that uses cycle->log can be called at this point | |
690 */ | |
691 exit(0); | |
692 } | |
693 | |
694 if (ngx_quit) { | |
695 ngx_quit = 0; | |
696 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
697 "gracefully shutting down"); | |
698 ngx_setproctitle("worker process is shutting down"); | |
699 | |
700 if (!ngx_exiting) { | |
701 ngx_close_listening_sockets(cycle); | |
702 ngx_exiting = 1; | |
703 } | |
704 } | |
705 | |
706 if (ngx_reopen) { | |
707 ngx_reopen = 0; | |
708 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
709 ngx_reopen_files(cycle, -1); | |
710 } | |
711 } | |
712 } | |
713 | |
714 | |
715 static void ngx_worker_process_init(ngx_cycle_t *cycle) | |
716 { | |
561 sigset_t set; | 717 sigset_t set; |
562 ngx_err_t err; | |
563 ngx_int_t n; | 718 ngx_int_t n; |
564 ngx_uint_t i; | 719 ngx_uint_t i; |
565 struct timeval tv; | 720 struct timeval tv; |
721 ngx_core_conf_t *ccf; | |
566 ngx_listening_t *ls; | 722 ngx_listening_t *ls; |
567 ngx_core_conf_t *ccf; | |
568 ngx_connection_t *c; | |
569 | |
570 | 723 |
571 ngx_gettimeofday(&tv); | 724 ngx_gettimeofday(&tv); |
572 | 725 |
573 ngx_start_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000; | 726 ngx_start_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000; |
574 ngx_old_elapsed_msec = 0; | 727 ngx_old_elapsed_msec = 0; |
647 continue; | 800 continue; |
648 } | 801 } |
649 | 802 |
650 if (close(ngx_processes[n].channel[1]) == -1) { | 803 if (close(ngx_processes[n].channel[1]) == -1) { |
651 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 804 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
652 "close() failed"); | 805 "close() channel failed"); |
653 } | 806 } |
654 } | 807 } |
655 | 808 |
656 if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) { | 809 if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) { |
657 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 810 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
658 "close() failed"); | 811 "close() channel failed"); |
659 } | 812 } |
660 | 813 |
661 #if 0 | 814 #if 0 |
662 ngx_last_process = 0; | 815 ngx_last_process = 0; |
663 #endif | 816 #endif |
666 ngx_channel_handler) == NGX_ERROR) | 819 ngx_channel_handler) == NGX_ERROR) |
667 { | 820 { |
668 /* fatal */ | 821 /* fatal */ |
669 exit(2); | 822 exit(2); |
670 } | 823 } |
671 | |
672 ngx_setproctitle("worker process"); | |
673 | |
674 #if (NGX_THREADS) | |
675 | |
676 if (ngx_time_mutex_init(cycle->log) == NGX_ERROR) { | |
677 /* fatal */ | |
678 exit(2); | |
679 } | |
680 | |
681 if (ngx_threads_n) { | |
682 if (ngx_init_threads(ngx_threads_n, | |
683 ccf->thread_stack_size, cycle) == NGX_ERROR) | |
684 { | |
685 /* fatal */ | |
686 exit(2); | |
687 } | |
688 | |
689 err = ngx_thread_key_create(&ngx_core_tls_key); | |
690 if (err != 0) { | |
691 ngx_log_error(NGX_LOG_ALERT, cycle->log, err, | |
692 ngx_thread_key_create_n " failed"); | |
693 /* fatal */ | |
694 exit(2); | |
695 } | |
696 | |
697 for (n = 0; n < ngx_threads_n; n++) { | |
698 | |
699 if (!(ngx_threads[n].cv = ngx_cond_init(cycle->log))) { | |
700 /* fatal */ | |
701 exit(2); | |
702 } | |
703 | |
704 if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid, | |
705 ngx_worker_thread_cycle, | |
706 (void *) &ngx_threads[n], cycle->log) != 0) | |
707 { | |
708 /* fatal */ | |
709 exit(2); | |
710 } | |
711 } | |
712 } | |
713 | |
714 #endif | |
715 | |
716 for ( ;; ) { | |
717 if (ngx_exiting | |
718 && ngx_event_timer_rbtree == &ngx_event_timer_sentinel) | |
719 { | |
720 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
721 | |
722 | |
723 #if (NGX_THREADS) | |
724 ngx_terminate = 1; | |
725 | |
726 ngx_wakeup_worker_threads(cycle); | |
727 #endif | |
728 | |
729 /* | |
730 * we do not destroy cycle->pool here because a signal handler | |
731 * that uses cycle->log can be called at this point | |
732 */ | |
733 exit(0); | |
734 } | |
735 | |
736 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
737 | |
738 ngx_process_events(cycle); | |
739 | |
740 if (ngx_terminate) { | |
741 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
742 | |
743 #if (NGX_THREADS) | |
744 ngx_wakeup_worker_threads(cycle); | |
745 #endif | |
746 | |
747 /* | |
748 * we do not destroy cycle->pool here because a signal handler | |
749 * that uses cycle->log can be called at this point | |
750 */ | |
751 exit(0); | |
752 } | |
753 | |
754 if (ngx_quit) { | |
755 ngx_quit = 0; | |
756 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
757 "gracefully shutting down"); | |
758 ngx_setproctitle("worker process is shutting down"); | |
759 | |
760 if (!ngx_exiting) { | |
761 ngx_close_listening_sockets(cycle); | |
762 ngx_exiting = 1; | |
763 } | |
764 } | |
765 | |
766 if (ngx_reopen) { | |
767 ngx_reopen = 0; | |
768 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
769 ngx_reopen_files(cycle, -1); | |
770 } | |
771 } | |
772 } | 824 } |
773 | 825 |
774 | 826 |
775 static void ngx_channel_handler(ngx_event_t *ev) | 827 static void ngx_channel_handler(ngx_event_t *ev) |
776 { | 828 { |
777 ngx_int_t n; | 829 ngx_int_t n; |
778 ngx_channel_t ch; | 830 ngx_channel_t ch; |
779 ngx_connection_t *c; | 831 ngx_connection_t *c; |
832 | |
833 if (ev->timedout) { | |
834 ev->timedout = 0; | |
835 return; | |
836 } | |
780 | 837 |
781 c = ev->data; | 838 c = ev->data; |
782 | 839 |
783 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler"); | 840 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler"); |
784 | 841 |
832 "close channel s:%i pid:%P our:%P fd:%d", | 889 "close channel s:%i pid:%P our:%P fd:%d", |
833 ch.slot, ch.pid, ngx_processes[ch.slot].pid, | 890 ch.slot, ch.pid, ngx_processes[ch.slot].pid, |
834 ngx_processes[ch.slot].channel[0]); | 891 ngx_processes[ch.slot].channel[0]); |
835 | 892 |
836 if (close(ngx_processes[ch.slot].channel[0]) == -1) { | 893 if (close(ngx_processes[ch.slot].channel[0]) == -1) { |
837 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "close() failed"); | 894 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, |
895 "close() channel failed"); | |
838 } | 896 } |
839 | 897 |
840 ngx_processes[ch.slot].channel[0] = -1; | 898 ngx_processes[ch.slot].channel[0] = -1; |
841 break; | 899 break; |
842 } | 900 } |
894 | 952 |
895 sigset_t set; | 953 sigset_t set; |
896 ngx_err_t err; | 954 ngx_err_t err; |
897 ngx_core_tls_t *tls; | 955 ngx_core_tls_t *tls; |
898 ngx_cycle_t *cycle; | 956 ngx_cycle_t *cycle; |
899 struct timeval tv; | |
900 | 957 |
901 thr->cv->tid = ngx_thread_self(); | 958 thr->cv->tid = ngx_thread_self(); |
902 | 959 |
903 cycle = (ngx_cycle_t *) ngx_cycle; | 960 cycle = (ngx_cycle_t *) ngx_cycle; |
904 | 961 |
970 } | 1027 } |
971 } | 1028 } |
972 } | 1029 } |
973 | 1030 |
974 #endif | 1031 #endif |
1032 | |
1033 | |
1034 static void ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data) | |
1035 { | |
1036 ngx_uint_t i; | |
1037 ngx_gc_t ctx; | |
1038 ngx_path_t **path; | |
1039 ngx_event_t *ev; | |
1040 | |
1041 ngx_worker_process_init(cycle); | |
1042 | |
1043 ev = &cycle->read_events[ngx_channel]; | |
1044 | |
1045 ngx_accept_mutex = NULL; | |
1046 | |
1047 ngx_setproctitle("garbage collector"); | |
1048 | |
1049 #if 0 | |
1050 ngx_add_timer(ev, 60 * 1000); | |
1051 #endif | |
1052 | |
1053 for ( ;; ) { | |
1054 | |
1055 if (ngx_terminate || ngx_quit) { | |
1056 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
1057 exit(0); | |
1058 } | |
1059 | |
1060 if (ngx_reopen) { | |
1061 ngx_reopen = 0; | |
1062 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
1063 ngx_reopen_files(cycle, -1); | |
1064 } | |
1065 | |
1066 path = cycle->pathes.elts; | |
1067 for (i = 0; i < cycle->pathes.nelts; i++) { | |
1068 ctx.path = path[i]; | |
1069 ctx.log = cycle->log; | |
1070 ctx.handler = path[i]->gc_handler; | |
1071 | |
1072 ngx_collect_garbage(&ctx, &path[i]->name, 0); | |
1073 } | |
1074 | |
1075 ngx_add_timer(ev, 60 * 60 * 1000); | |
1076 | |
1077 ngx_process_events(cycle); | |
1078 } | |
1079 } |