Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_process_cycle.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 #include <ngx_channel.h>
12 
13 
14 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
15  ngx_int_t type);
16 static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle,
17  ngx_uint_t respawn);
18 static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch);
19 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
20 static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
21 static void ngx_master_process_exit(ngx_cycle_t *cycle);
22 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
23 static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker);
24 static void ngx_worker_process_exit(ngx_cycle_t *cycle);
25 static void ngx_channel_handler(ngx_event_t *ev);
26 #if (NGX_THREADS)
27 static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle);
28 static ngx_thread_value_t ngx_worker_thread_cycle(void *data);
29 #endif
30 static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data);
31 static void ngx_cache_manager_process_handler(ngx_event_t *ev);
32 static void ngx_cache_loader_process_handler(ngx_event_t *ev);
33 
34 
38 
39 sig_atomic_t ngx_reap;
40 sig_atomic_t ngx_sigio;
41 sig_atomic_t ngx_sigalrm;
42 sig_atomic_t ngx_terminate;
43 sig_atomic_t ngx_quit;
44 sig_atomic_t ngx_debug_quit;
46 sig_atomic_t ngx_reconfigure;
47 sig_atomic_t ngx_reopen;
48 
49 sig_atomic_t ngx_change_binary;
53 
54 sig_atomic_t ngx_noaccept;
57 
58 
59 #if (NGX_THREADS)
60 volatile ngx_thread_t ngx_threads[NGX_MAX_THREADS];
61 ngx_int_t ngx_threads_n;
62 #endif
63 
64 
65 static u_char master_process[] = "master process";
66 
67 
68 static ngx_cache_manager_ctx_t ngx_cache_manager_ctx = {
69  ngx_cache_manager_process_handler, "cache manager process", 0
70 };
71 
72 static ngx_cache_manager_ctx_t ngx_cache_loader_ctx = {
73  ngx_cache_loader_process_handler, "cache loader process", 60000
74 };
75 
76 
77 static ngx_cycle_t ngx_exit_cycle;
78 static ngx_log_t ngx_exit_log;
79 static ngx_open_file_t ngx_exit_log_file;
80 
81 
82 void
84 {
85  char *title;
86  u_char *p;
87  size_t size;
88  ngx_int_t i;
89  ngx_uint_t n, sigio;
90  sigset_t set;
91  struct itimerval itv;
92  ngx_uint_t live;
93  ngx_msec_t delay;
94  ngx_listening_t *ls;
95  ngx_core_conf_t *ccf;
96 
97  sigemptyset(&set);
98  sigaddset(&set, SIGCHLD);
99  sigaddset(&set, SIGALRM);
100  sigaddset(&set, SIGIO);
101  sigaddset(&set, SIGINT);
102  sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
103  sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
104  sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
105  sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
106  sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
107  sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
108 
109  if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
111  "sigprocmask() failed");
112  }
113 
114  sigemptyset(&set);
115 
116 
117  size = sizeof(master_process);
118 
119  for (i = 0; i < ngx_argc; i++) {
120  size += ngx_strlen(ngx_argv[i]) + 1;
121  }
122 
123  title = ngx_pnalloc(cycle->pool, size);
124 
125  p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);
126  for (i = 0; i < ngx_argc; i++) {
127  *p++ = ' ';
128  p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
129  }
130 
131  ngx_setproctitle(title);
132 
133 
135 
136  ngx_start_worker_processes(cycle, ccf->worker_processes,
138  ngx_start_cache_manager_processes(cycle, 0);
139 
140  ngx_new_binary = 0;
141  delay = 0;
142  sigio = 0;
143  live = 1;
144 
145  for ( ;; ) {
146  if (delay) {
147  if (ngx_sigalrm) {
148  sigio = 0;
149  delay *= 2;
150  ngx_sigalrm = 0;
151  }
152 
154  "termination cycle: %d", delay);
155 
156  itv.it_interval.tv_sec = 0;
157  itv.it_interval.tv_usec = 0;
158  itv.it_value.tv_sec = delay / 1000;
159  itv.it_value.tv_usec = (delay % 1000 ) * 1000;
160 
161  if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
163  "setitimer() failed");
164  }
165  }
166 
167  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");
168 
169  sigsuspend(&set);
170 
171  ngx_time_update();
172 
174  "wake up, sigio %i", sigio);
175 
176  if (ngx_reap) {
177  ngx_reap = 0;
178  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");
179 
180  live = ngx_reap_children(cycle);
181  }
182 
183  if (!live && (ngx_terminate || ngx_quit)) {
184  ngx_master_process_exit(cycle);
185  }
186 
187  if (ngx_terminate) {
188  if (delay == 0) {
189  delay = 50;
190  }
191 
192  if (sigio) {
193  sigio--;
194  continue;
195  }
196 
197  sigio = ccf->worker_processes + 2 /* cache processes */;
198 
199  if (delay > 1000) {
200  ngx_signal_worker_processes(cycle, SIGKILL);
201  } else {
202  ngx_signal_worker_processes(cycle,
204  }
205 
206  continue;
207  }
208 
209  if (ngx_quit) {
210  ngx_signal_worker_processes(cycle,
212 
213  ls = cycle->listening.elts;
214  for (n = 0; n < cycle->listening.nelts; n++) {
215  if (ngx_close_socket(ls[n].fd) == -1) {
217  ngx_close_socket_n " %V failed",
218  &ls[n].addr_text);
219  }
220  }
221  cycle->listening.nelts = 0;
222 
223  continue;
224  }
225 
226  if (ngx_reconfigure) {
227  ngx_reconfigure = 0;
228 
229  if (ngx_new_binary) {
230  ngx_start_worker_processes(cycle, ccf->worker_processes,
232  ngx_start_cache_manager_processes(cycle, 0);
233  ngx_noaccepting = 0;
234 
235  continue;
236  }
237 
238  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
239 
240  cycle = ngx_init_cycle(cycle);
241  if (cycle == NULL) {
242  cycle = (ngx_cycle_t *) ngx_cycle;
243  continue;
244  }
245 
246  ngx_cycle = cycle;
247  ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
249  ngx_start_worker_processes(cycle, ccf->worker_processes,
251  ngx_start_cache_manager_processes(cycle, 1);
252 
253  /* allow new processes to start */
254  ngx_msleep(100);
255 
256  live = 1;
257  ngx_signal_worker_processes(cycle,
259  }
260 
261  if (ngx_restart) {
262  ngx_restart = 0;
263  ngx_start_worker_processes(cycle, ccf->worker_processes,
265  ngx_start_cache_manager_processes(cycle, 0);
266  live = 1;
267  }
268 
269  if (ngx_reopen) {
270  ngx_reopen = 0;
271  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
272  ngx_reopen_files(cycle, ccf->user);
273  ngx_signal_worker_processes(cycle,
275  }
276 
277  if (ngx_change_binary) {
278  ngx_change_binary = 0;
279  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
281  }
282 
283  if (ngx_noaccept) {
284  ngx_noaccept = 0;
285  ngx_noaccepting = 1;
286  ngx_signal_worker_processes(cycle,
288  }
289  }
290 }
291 
292 
293 void
295 {
296  ngx_uint_t i;
297 
298  if (ngx_set_environment(cycle, NULL) == NULL) {
299  /* fatal */
300  exit(2);
301  }
302 
303  for (i = 0; ngx_modules[i]; i++) {
304  if (ngx_modules[i]->init_process) {
305  if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
306  /* fatal */
307  exit(2);
308  }
309  }
310  }
311 
312  for ( ;; ) {
313  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
314 
316 
317  if (ngx_terminate || ngx_quit) {
318 
319  for (i = 0; ngx_modules[i]; i++) {
320  if (ngx_modules[i]->exit_process) {
321  ngx_modules[i]->exit_process(cycle);
322  }
323  }
324 
325  ngx_master_process_exit(cycle);
326  }
327 
328  if (ngx_reconfigure) {
329  ngx_reconfigure = 0;
330  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
331 
332  cycle = ngx_init_cycle(cycle);
333  if (cycle == NULL) {
334  cycle = (ngx_cycle_t *) ngx_cycle;
335  continue;
336  }
337 
338  ngx_cycle = cycle;
339  }
340 
341  if (ngx_reopen) {
342  ngx_reopen = 0;
343  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
344  ngx_reopen_files(cycle, (ngx_uid_t) -1);
345  }
346  }
347 }
348 
349 
350 static void
351 ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
352 {
353  ngx_int_t i;
354  ngx_channel_t ch;
355 
356  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
357 
359 
360  for (i = 0; i < n; i++) {
361 
362  ngx_spawn_process(cycle, ngx_worker_process_cycle,
363  (void *) (intptr_t) i, "worker process", type);
364 
366  ch.slot = ngx_process_slot;
368 
369  ngx_pass_open_channel(cycle, &ch);
370  }
371 }
372 
373 
374 static void
375 ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
376 {
377  ngx_uint_t i, manager, loader;
378  ngx_path_t **path;
379  ngx_channel_t ch;
380 
381  manager = 0;
382  loader = 0;
383 
384  path = ngx_cycle->paths.elts;
385  for (i = 0; i < ngx_cycle->paths.nelts; i++) {
386 
387  if (path[i]->manager) {
388  manager = 1;
389  }
390 
391  if (path[i]->loader) {
392  loader = 1;
393  }
394  }
395 
396  if (manager == 0) {
397  return;
398  }
399 
400  ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
401  &ngx_cache_manager_ctx, "cache manager process",
403 
406  ch.slot = ngx_process_slot;
408 
409  ngx_pass_open_channel(cycle, &ch);
410 
411  if (loader == 0) {
412  return;
413  }
414 
415  ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
416  &ngx_cache_loader_ctx, "cache loader process",
418 
421  ch.slot = ngx_process_slot;
423 
424  ngx_pass_open_channel(cycle, &ch);
425 }
426 
427 
428 static void
429 ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
430 {
431  ngx_int_t i;
432 
433  for (i = 0; i < ngx_last_process; i++) {
434 
435  if (i == ngx_process_slot
436  || ngx_processes[i].pid == -1
437  || ngx_processes[i].channel[0] == -1)
438  {
439  continue;
440  }
441 
443  "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
444  ch->slot, ch->pid, ch->fd,
445  i, ngx_processes[i].pid,
446  ngx_processes[i].channel[0]);
447 
448  /* TODO: NGX_AGAIN */
449 
450  ngx_write_channel(ngx_processes[i].channel[0],
451  ch, sizeof(ngx_channel_t), cycle->log);
452  }
453 }
454 
455 
456 static void
457 ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
458 {
459  ngx_int_t i;
460  ngx_err_t err;
461  ngx_channel_t ch;
462 
463 #if (NGX_BROKEN_SCM_RIGHTS)
464 
465  ch.command = 0;
466 
467 #else
468 
469  switch (signo) {
470 
472  ch.command = NGX_CMD_QUIT;
473  break;
474 
476  ch.command = NGX_CMD_TERMINATE;
477  break;
478 
480  ch.command = NGX_CMD_REOPEN;
481  break;
482 
483  default:
484  ch.command = 0;
485  }
486 
487 #endif
488 
489  ch.fd = -1;
490 
491 
492  for (i = 0; i < ngx_last_process; i++) {
493 
495  "child: %d %P e:%d t:%d d:%d r:%d j:%d",
496  i,
497  ngx_processes[i].pid,
503 
504  if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
505  continue;
506  }
507 
508  if (ngx_processes[i].just_spawn) {
510  continue;
511  }
512 
513  if (ngx_processes[i].exiting
515  {
516  continue;
517  }
518 
519  if (ch.command) {
520  if (ngx_write_channel(ngx_processes[i].channel[0],
521  &ch, sizeof(ngx_channel_t), cycle->log)
522  == NGX_OK)
523  {
524  if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
525  ngx_processes[i].exiting = 1;
526  }
527 
528  continue;
529  }
530  }
531 
533  "kill (%P, %d)" , ngx_processes[i].pid, signo);
534 
535  if (kill(ngx_processes[i].pid, signo) == -1) {
536  err = ngx_errno;
537  ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
538  "kill(%P, %d) failed", ngx_processes[i].pid, signo);
539 
540  if (err == NGX_ESRCH) {
541  ngx_processes[i].exited = 1;
542  ngx_processes[i].exiting = 0;
543  ngx_reap = 1;
544  }
545 
546  continue;
547  }
548 
549  if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
550  ngx_processes[i].exiting = 1;
551  }
552  }
553 }
554 
555 
556 static ngx_uint_t
557 ngx_reap_children(ngx_cycle_t *cycle)
558 {
559  ngx_int_t i, n;
560  ngx_uint_t live;
561  ngx_channel_t ch;
562  ngx_core_conf_t *ccf;
563 
565  ch.fd = -1;
566 
567  live = 0;
568  for (i = 0; i < ngx_last_process; i++) {
569 
571  "child: %d %P e:%d t:%d d:%d r:%d j:%d",
572  i,
573  ngx_processes[i].pid,
579 
580  if (ngx_processes[i].pid == -1) {
581  continue;
582  }
583 
584  if (ngx_processes[i].exited) {
585 
586  if (!ngx_processes[i].detached) {
587  ngx_close_channel(ngx_processes[i].channel, cycle->log);
588 
589  ngx_processes[i].channel[0] = -1;
590  ngx_processes[i].channel[1] = -1;
591 
592  ch.pid = ngx_processes[i].pid;
593  ch.slot = i;
594 
595  for (n = 0; n < ngx_last_process; n++) {
596  if (ngx_processes[n].exited
597  || ngx_processes[n].pid == -1
598  || ngx_processes[n].channel[0] == -1)
599  {
600  continue;
601  }
602 
604  "pass close channel s:%i pid:%P to:%P",
605  ch.slot, ch.pid, ngx_processes[n].pid);
606 
607  /* TODO: NGX_AGAIN */
608 
609  ngx_write_channel(ngx_processes[n].channel[0],
610  &ch, sizeof(ngx_channel_t), cycle->log);
611  }
612  }
613 
614  if (ngx_processes[i].respawn
615  && !ngx_processes[i].exiting
616  && !ngx_terminate
617  && !ngx_quit)
618  {
619  if (ngx_spawn_process(cycle, ngx_processes[i].proc,
620  ngx_processes[i].data,
621  ngx_processes[i].name, i)
622  == NGX_INVALID_PID)
623  {
624  ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
625  "could not respawn %s",
626  ngx_processes[i].name);
627  continue;
628  }
629 
630 
633  ch.slot = ngx_process_slot;
635 
636  ngx_pass_open_channel(cycle, &ch);
637 
638  live = 1;
639 
640  continue;
641  }
642 
643  if (ngx_processes[i].pid == ngx_new_binary) {
644 
645  ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
647 
648  if (ngx_rename_file((char *) ccf->oldpid.data,
649  (char *) ccf->pid.data)
650  == NGX_FILE_ERROR)
651  {
653  ngx_rename_file_n " %s back to %s failed "
654  "after the new binary process \"%s\" exited",
655  ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
656  }
657 
658  ngx_new_binary = 0;
659  if (ngx_noaccepting) {
660  ngx_restart = 1;
661  ngx_noaccepting = 0;
662  }
663  }
664 
665  if (i == ngx_last_process - 1) {
666  ngx_last_process--;
667 
668  } else {
669  ngx_processes[i].pid = -1;
670  }
671 
672  } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
673  live = 1;
674  }
675  }
676 
677  return live;
678 }
679 
680 
681 static void
682 ngx_master_process_exit(ngx_cycle_t *cycle)
683 {
684  ngx_uint_t i;
685 
686  ngx_delete_pidfile(cycle);
687 
688  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
689 
690  for (i = 0; ngx_modules[i]; i++) {
691  if (ngx_modules[i]->exit_master) {
692  ngx_modules[i]->exit_master(cycle);
693  }
694  }
695 
697 
698  /*
699  * Copy ngx_cycle->log related data to the special static exit cycle,
700  * log, and log file structures enough to allow a signal handler to log.
701  * The handler may be called when standard ngx_cycle->log allocated from
702  * ngx_cycle->pool is already destroyed.
703  */
704 
705  ngx_exit_log_file.fd = ngx_cycle->log->file->fd;
706 
707  ngx_exit_log = *ngx_cycle->log;
708  ngx_exit_log.file = &ngx_exit_log_file;
709 
710  ngx_exit_cycle.log = &ngx_exit_log;
711  ngx_exit_cycle.files = ngx_cycle->files;
712  ngx_exit_cycle.files_n = ngx_cycle->files_n;
713  ngx_cycle = &ngx_exit_cycle;
714 
715  ngx_destroy_pool(cycle->pool);
716 
717  exit(0);
718 }
719 
720 
721 static void
722 ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
723 {
724  ngx_int_t worker = (intptr_t) data;
725 
726  ngx_uint_t i;
727  ngx_connection_t *c;
728 
730 
731  ngx_worker_process_init(cycle, worker);
732 
733  ngx_setproctitle("worker process");
734 
735 #if (NGX_THREADS)
736  {
737  ngx_int_t n;
738  ngx_err_t err;
739  ngx_core_conf_t *ccf;
740 
742 
743  if (ngx_threads_n) {
744  if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle)
745  == NGX_ERROR)
746  {
747  /* fatal */
748  exit(2);
749  }
750 
751  err = ngx_thread_key_create(&ngx_core_tls_key);
752  if (err != 0) {
753  ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
754  ngx_thread_key_create_n " failed");
755  /* fatal */
756  exit(2);
757  }
758 
759  for (n = 0; n < ngx_threads_n; n++) {
760 
761  ngx_threads[n].cv = ngx_cond_init(cycle->log);
762 
763  if (ngx_threads[n].cv == NULL) {
764  /* fatal */
765  exit(2);
766  }
767 
768  if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid,
769  ngx_worker_thread_cycle,
770  (void *) &ngx_threads[n], cycle->log)
771  != 0)
772  {
773  /* fatal */
774  exit(2);
775  }
776  }
777  }
778  }
779 #endif
780 
781  for ( ;; ) {
782 
783  if (ngx_exiting) {
784 
785  c = cycle->connections;
786 
787  for (i = 0; i < cycle->connection_n; i++) {
788 
789  /* THREAD: lock */
790 
791  if (c[i].fd != -1 && c[i].idle) {
792  c[i].close = 1;
793  c[i].read->handler(c[i].read);
794  }
795  }
796 
798  {
799  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
800 
801  ngx_worker_process_exit(cycle);
802  }
803  }
804 
805  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
806 
808 
809  if (ngx_terminate) {
810  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
811 
812  ngx_worker_process_exit(cycle);
813  }
814 
815  if (ngx_quit) {
816  ngx_quit = 0;
817  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
818  "gracefully shutting down");
819  ngx_setproctitle("worker process is shutting down");
820 
821  if (!ngx_exiting) {
823  ngx_exiting = 1;
824  }
825  }
826 
827  if (ngx_reopen) {
828  ngx_reopen = 0;
829  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
830  ngx_reopen_files(cycle, -1);
831  }
832  }
833 }
834 
835 
836 static void
837 ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
838 {
839  sigset_t set;
840  uint64_t cpu_affinity;
841  ngx_int_t n;
842  ngx_uint_t i;
843  struct rlimit rlmt;
844  ngx_core_conf_t *ccf;
845  ngx_listening_t *ls;
846 
847  if (ngx_set_environment(cycle, NULL) == NULL) {
848  /* fatal */
849  exit(2);
850  }
851 
853 
854  if (worker >= 0 && ccf->priority != 0) {
855  if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
857  "setpriority(%d) failed", ccf->priority);
858  }
859  }
860 
861  if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
862  rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
863  rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
864 
865  if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
867  "setrlimit(RLIMIT_NOFILE, %i) failed",
868  ccf->rlimit_nofile);
869  }
870  }
871 
872  if (ccf->rlimit_core != NGX_CONF_UNSET) {
873  rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
874  rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
875 
876  if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
878  "setrlimit(RLIMIT_CORE, %O) failed",
879  ccf->rlimit_core);
880  }
881  }
882 
883 #ifdef RLIMIT_SIGPENDING
884  if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
885  rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
886  rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;
887 
888  if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
890  "setrlimit(RLIMIT_SIGPENDING, %i) failed",
891  ccf->rlimit_sigpending);
892  }
893  }
894 #endif
895 
896  if (geteuid() == 0) {
897  if (setgid(ccf->group) == -1) {
899  "setgid(%d) failed", ccf->group);
900  /* fatal */
901  exit(2);
902  }
903 
904  if (initgroups(ccf->username, ccf->group) == -1) {
906  "initgroups(%s, %d) failed",
907  ccf->username, ccf->group);
908  }
909 
910  if (setuid(ccf->user) == -1) {
912  "setuid(%d) failed", ccf->user);
913  /* fatal */
914  exit(2);
915  }
916  }
917 
918  if (worker >= 0) {
919  cpu_affinity = ngx_get_cpu_affinity(worker);
920 
921  if (cpu_affinity) {
922  ngx_setaffinity(cpu_affinity, cycle->log);
923  }
924  }
925 
926 #if (NGX_HAVE_PR_SET_DUMPABLE)
927 
928  /* allow coredump after setuid() in Linux 2.4.x */
929 
930  if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
932  "prctl(PR_SET_DUMPABLE) failed");
933  }
934 
935 #endif
936 
937  if (ccf->working_directory.len) {
938  if (chdir((char *) ccf->working_directory.data) == -1) {
940  "chdir(\"%s\") failed", ccf->working_directory.data);
941  /* fatal */
942  exit(2);
943  }
944  }
945 
946  sigemptyset(&set);
947 
948  if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
950  "sigprocmask() failed");
951  }
952 
953  /*
954  * disable deleting previous events for the listening sockets because
955  * in the worker processes there are no events at all at this point
956  */
957  ls = cycle->listening.elts;
958  for (i = 0; i < cycle->listening.nelts; i++) {
959  ls[i].previous = NULL;
960  }
961 
962  for (i = 0; ngx_modules[i]; i++) {
963  if (ngx_modules[i]->init_process) {
964  if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
965  /* fatal */
966  exit(2);
967  }
968  }
969  }
970 
971  for (n = 0; n < ngx_last_process; n++) {
972 
973  if (ngx_processes[n].pid == -1) {
974  continue;
975  }
976 
977  if (n == ngx_process_slot) {
978  continue;
979  }
980 
981  if (ngx_processes[n].channel[1] == -1) {
982  continue;
983  }
984 
985  if (close(ngx_processes[n].channel[1]) == -1) {
987  "close() channel failed");
988  }
989  }
990 
991  if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
993  "close() channel failed");
994  }
995 
996 #if 0
997  ngx_last_process = 0;
998 #endif
999 
1001  ngx_channel_handler)
1002  == NGX_ERROR)
1003  {
1004  /* fatal */
1005  exit(2);
1006  }
1007 }
1008 
1009 
1010 static void
1011 ngx_worker_process_exit(ngx_cycle_t *cycle)
1012 {
1013  ngx_uint_t i;
1014  ngx_connection_t *c;
1015 
1016 #if (NGX_THREADS)
1017  ngx_terminate = 1;
1018 
1019  ngx_wakeup_worker_threads(cycle);
1020 #endif
1021 
1022  for (i = 0; ngx_modules[i]; i++) {
1023  if (ngx_modules[i]->exit_process) {
1024  ngx_modules[i]->exit_process(cycle);
1025  }
1026  }
1027 
1028  if (ngx_exiting) {
1029  c = cycle->connections;
1030  for (i = 0; i < cycle->connection_n; i++) {
1031  if (c[i].fd != -1
1032  && c[i].read
1033  && !c[i].read->accept
1034  && !c[i].read->channel
1035  && !c[i].read->resolver)
1036  {
1037  ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
1038  "open socket #%d left in connection %ui",
1039  c[i].fd, i);
1040  ngx_debug_quit = 1;
1041  }
1042  }
1043 
1044  if (ngx_debug_quit) {
1045  ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
1046  ngx_debug_point();
1047  }
1048  }
1049 
1050  /*
1051  * Copy ngx_cycle->log related data to the special static exit cycle,
1052  * log, and log file structures enough to allow a signal handler to log.
1053  * The handler may be called when standard ngx_cycle->log allocated from
1054  * ngx_cycle->pool is already destroyed.
1055  */
1056 
1057  ngx_exit_log_file.fd = ngx_cycle->log->file->fd;
1058 
1059  ngx_exit_log = *ngx_cycle->log;
1060  ngx_exit_log.file = &ngx_exit_log_file;
1061 
1062  ngx_exit_cycle.log = &ngx_exit_log;
1063  ngx_exit_cycle.files = ngx_cycle->files;
1064  ngx_exit_cycle.files_n = ngx_cycle->files_n;
1065  ngx_cycle = &ngx_exit_cycle;
1066 
1067  ngx_destroy_pool(cycle->pool);
1068 
1069  ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit");
1070 
1071  exit(0);
1072 }
1073 
1074 
1075 static void
1076 ngx_channel_handler(ngx_event_t *ev)
1077 {
1078  ngx_int_t n;
1079  ngx_channel_t ch;
1080  ngx_connection_t *c;
1081 
1082  if (ev->timedout) {
1083  ev->timedout = 0;
1084  return;
1085  }
1086 
1087  c = ev->data;
1088 
1089  ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");
1090 
1091  for ( ;; ) {
1092 
1093  n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
1094 
1095  ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
1096 
1097  if (n == NGX_ERROR) {
1098 
1100  ngx_del_conn(c, 0);
1101  }
1102 
1104  return;
1105  }
1106 
1108  if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
1109  return;
1110  }
1111  }
1112 
1113  if (n == NGX_AGAIN) {
1114  return;
1115  }
1116 
1118  "channel command: %d", ch.command);
1119 
1120  switch (ch.command) {
1121 
1122  case NGX_CMD_QUIT:
1123  ngx_quit = 1;
1124  break;
1125 
1126  case NGX_CMD_TERMINATE:
1127  ngx_terminate = 1;
1128  break;
1129 
1130  case NGX_CMD_REOPEN:
1131  ngx_reopen = 1;
1132  break;
1133 
1134  case NGX_CMD_OPEN_CHANNEL:
1135 
1137  "get channel s:%i pid:%P fd:%d",
1138  ch.slot, ch.pid, ch.fd);
1139 
1140  ngx_processes[ch.slot].pid = ch.pid;
1141  ngx_processes[ch.slot].channel[0] = ch.fd;
1142  break;
1143 
1144  case NGX_CMD_CLOSE_CHANNEL:
1145 
1147  "close channel s:%i pid:%P our:%P fd:%d",
1148  ch.slot, ch.pid, ngx_processes[ch.slot].pid,
1149  ngx_processes[ch.slot].channel[0]);
1150 
1151  if (close(ngx_processes[ch.slot].channel[0]) == -1) {
1153  "close() channel failed");
1154  }
1155 
1156  ngx_processes[ch.slot].channel[0] = -1;
1157  break;
1158  }
1159  }
1160 }
1161 
1162 
1163 #if (NGX_THREADS)
1164 
1165 static void
1166 ngx_wakeup_worker_threads(ngx_cycle_t *cycle)
1167 {
1168  ngx_int_t i;
1169  ngx_uint_t live;
1170 
1171  for ( ;; ) {
1172 
1173  live = 0;
1174 
1175  for (i = 0; i < ngx_threads_n; i++) {
1176  if (ngx_threads[i].state < NGX_THREAD_EXIT) {
1177  if (ngx_cond_signal(ngx_threads[i].cv) == NGX_ERROR) {
1178  ngx_threads[i].state = NGX_THREAD_DONE;
1179 
1180  } else {
1181  live = 1;
1182  }
1183  }
1184 
1185  if (ngx_threads[i].state == NGX_THREAD_EXIT) {
1186  ngx_thread_join(ngx_threads[i].tid, NULL);
1187  ngx_threads[i].state = NGX_THREAD_DONE;
1188  }
1189  }
1190 
1191  if (live == 0) {
1193  "all worker threads are joined");
1194 
1195  /* STUB */
1196  ngx_done_events(cycle);
1197  ngx_mutex_destroy(ngx_event_timer_mutex);
1198  ngx_mutex_destroy(ngx_posted_events_mutex);
1199 
1200  return;
1201  }
1202 
1203  ngx_sched_yield();
1204  }
1205 }
1206 
1207 
1208 static ngx_thread_value_t
1209 ngx_worker_thread_cycle(void *data)
1210 {
1211  ngx_thread_t *thr = data;
1212 
1213  sigset_t set;
1214  ngx_err_t err;
1215  ngx_core_tls_t *tls;
1216  ngx_cycle_t *cycle;
1217 
1218  cycle = (ngx_cycle_t *) ngx_cycle;
1219 
1220  sigemptyset(&set);
1221  sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
1222  sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
1223  sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
1224 
1225  err = ngx_thread_sigmask(SIG_BLOCK, &set, NULL);
1226  if (err) {
1227  ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
1228  ngx_thread_sigmask_n " failed");
1229  return (ngx_thread_value_t) 1;
1230  }
1231 
1233  "thread " NGX_TID_T_FMT " started", ngx_thread_self());
1234 
1235  ngx_setthrtitle("worker thread");
1236 
1237  tls = ngx_calloc(sizeof(ngx_core_tls_t), cycle->log);
1238  if (tls == NULL) {
1239  return (ngx_thread_value_t) 1;
1240  }
1241 
1242  err = ngx_thread_set_tls(ngx_core_tls_key, tls);
1243  if (err != 0) {
1244  ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
1245  ngx_thread_set_tls_n " failed");
1246  return (ngx_thread_value_t) 1;
1247  }
1248 
1249  ngx_mutex_lock(ngx_posted_events_mutex);
1250 
1251  for ( ;; ) {
1252  thr->state = NGX_THREAD_FREE;
1253 
1254  if (ngx_cond_wait(thr->cv, ngx_posted_events_mutex) == NGX_ERROR) {
1255  return (ngx_thread_value_t) 1;
1256  }
1257 
1258  if (ngx_terminate) {
1259  thr->state = NGX_THREAD_EXIT;
1260 
1261  ngx_mutex_unlock(ngx_posted_events_mutex);
1262 
1264  "thread " NGX_TID_T_FMT " is done",
1265  ngx_thread_self());
1266 
1267  return (ngx_thread_value_t) 0;
1268  }
1269 
1270  thr->state = NGX_THREAD_BUSY;
1271 
1272  if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) {
1273  return (ngx_thread_value_t) 1;
1274  }
1275 
1276  if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) {
1277  return (ngx_thread_value_t) 1;
1278  }
1279 
1280  if (ngx_process_changes) {
1281  if (ngx_process_changes(cycle, 1) == NGX_ERROR) {
1282  return (ngx_thread_value_t) 1;
1283  }
1284  }
1285  }
1286 }
1287 
1288 #endif
1289 
1290 
1291 static void
1292 ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
1293 {
1294  ngx_cache_manager_ctx_t *ctx = data;
1295 
1296  void *ident[4];
1297  ngx_event_t ev;
1298 
1299  /*
1300  * Set correct process type since closing listening Unix domain socket
1301  * in a master process also removes the Unix domain socket file.
1302  */
1304 
1306 
1307  /* Set a moderate number of connections for a helper process. */
1308  cycle->connection_n = 512;
1309 
1310  ngx_worker_process_init(cycle, -1);
1311 
1312  ngx_memzero(&ev, sizeof(ngx_event_t));
1313  ev.handler = ctx->handler;
1314  ev.data = ident;
1315  ev.log = cycle->log;
1316  ident[3] = (void *) -1;
1317 
1319 
1320  ngx_setproctitle(ctx->name);
1321 
1322  ngx_add_timer(&ev, ctx->delay);
1323 
1324  for ( ;; ) {
1325 
1326  if (ngx_terminate || ngx_quit) {
1327  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
1328  exit(0);
1329  }
1330 
1331  if (ngx_reopen) {
1332  ngx_reopen = 0;
1333  ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
1334  ngx_reopen_files(cycle, -1);
1335  }
1336 
1338  }
1339 }
1340 
1341 
1342 static void
1343 ngx_cache_manager_process_handler(ngx_event_t *ev)
1344 {
1345  time_t next, n;
1346  ngx_uint_t i;
1347  ngx_path_t **path;
1348 
1349  next = 60 * 60;
1350 
1351  path = ngx_cycle->paths.elts;
1352  for (i = 0; i < ngx_cycle->paths.nelts; i++) {
1353 
1354  if (path[i]->manager) {
1355  n = path[i]->manager(path[i]->data);
1356 
1357  next = (n <= next) ? n : next;
1358 
1359  ngx_time_update();
1360  }
1361  }
1362 
1363  if (next == 0) {
1364  next = 1;
1365  }
1366 
1367  ngx_add_timer(ev, next * 1000);
1368 }
1369 
1370 
1371 static void
1372 ngx_cache_loader_process_handler(ngx_event_t *ev)
1373 {
1374  ngx_uint_t i;
1375  ngx_path_t **path;
1376  ngx_cycle_t *cycle;
1377 
1378  cycle = (ngx_cycle_t *) ngx_cycle;
1379 
1380  path = cycle->paths.elts;
1381  for (i = 0; i < cycle->paths.nelts; i++) {
1382 
1383  if (ngx_terminate || ngx_quit) {
1384  break;
1385  }
1386 
1387  if (path[i]->loader) {
1388  path[i]->loader(path[i]->data);
1389  ngx_time_update();
1390  }
1391  }
1392 
1393  exit(0);
1394 }