comparison src/os/unix/ngx_process_cycle.c @ 16:74b1868dd3cd NGINX_0_1_8

nginx 0.1.8 *) 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 <http://sysoev.ru>
date Sat, 20 Nov 2004 00:00:00 +0300
parents 46833bd150cb
children 6f8b0dc0f8dd
comparison
equal deleted inserted replaced
15:0503cb60c4e4 16:74b1868dd3cd
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 }