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 static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data);
27 static void ngx_cache_manager_process_handler(ngx_event_t *ev);
28 static void ngx_cache_loader_process_handler(ngx_event_t *ev);
29
30 #if (NGX_HAVE_FSTACK)
31 extern int ff_mod_init(const char *conf, int proc_id, int proc_type);
32 ngx_int_t ngx_ff_process;
33 #endif
34
35 ngx_uint_t ngx_process;
36 ngx_uint_t ngx_worker;
37 ngx_pid_t ngx_pid;
38 ngx_pid_t ngx_parent;
39
40 sig_atomic_t ngx_reap;
41 sig_atomic_t ngx_sigio;
42 sig_atomic_t ngx_sigalrm;
43 sig_atomic_t ngx_terminate;
44 sig_atomic_t ngx_quit;
45 sig_atomic_t ngx_debug_quit;
46 ngx_uint_t ngx_exiting;
47 sig_atomic_t ngx_reconfigure;
48 sig_atomic_t ngx_reopen;
49
50 sig_atomic_t ngx_change_binary;
51 ngx_pid_t ngx_new_binary;
52 ngx_uint_t ngx_inherited;
53 ngx_uint_t ngx_daemonized;
54
55 sig_atomic_t ngx_noaccept;
56 ngx_uint_t ngx_noaccepting;
57 ngx_uint_t ngx_restart;
58
59
60 static u_char master_process[] = "master process";
61
62
63 static ngx_cache_manager_ctx_t ngx_cache_manager_ctx = {
64 ngx_cache_manager_process_handler, "cache manager process", 0
65 };
66
67 static ngx_cache_manager_ctx_t ngx_cache_loader_ctx = {
68 ngx_cache_loader_process_handler, "cache loader process", 60000
69 };
70
71
72 static ngx_cycle_t ngx_exit_cycle;
73 static ngx_log_t ngx_exit_log;
74 static ngx_open_file_t ngx_exit_log_file;
75
76 #if (NGX_HAVE_FSTACK)
77 static sem_t *ngx_ff_worker_sem;
78 #endif
79
80 void
ngx_master_process_cycle(ngx_cycle_t * cycle)81 ngx_master_process_cycle(ngx_cycle_t *cycle)
82 {
83 char *title;
84 u_char *p;
85 size_t size;
86 ngx_int_t i;
87 #if (NGX_HAVE_FSTACK)
88 ngx_uint_t sigio;
89 ngx_uint_t sig_worker_quit = 0;
90 #else
91 ngx_uint_t n, sigio;
92 #endif
93 sigset_t set;
94 struct itimerval itv;
95 ngx_uint_t live;
96 ngx_msec_t delay;
97 #if (!NGX_HAVE_FSTACK)
98 ngx_listening_t *ls;
99 #endif
100 ngx_core_conf_t *ccf;
101
102 sigemptyset(&set);
103 sigaddset(&set, SIGCHLD);
104 sigaddset(&set, SIGALRM);
105 sigaddset(&set, SIGIO);
106 sigaddset(&set, SIGINT);
107 sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
108 sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
109 sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
110 sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
111 sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
112 sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
113
114 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
115 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
116 "sigprocmask() failed");
117 }
118
119 sigemptyset(&set);
120
121
122 size = sizeof(master_process);
123
124 for (i = 0; i < ngx_argc; i++) {
125 size += ngx_strlen(ngx_argv[i]) + 1;
126 }
127
128 title = ngx_pnalloc(cycle->pool, size);
129 if (title == NULL) {
130 /* fatal */
131 exit(2);
132 }
133
134 p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);
135 for (i = 0; i < ngx_argc; i++) {
136 *p++ = ' ';
137 p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
138 }
139
140 ngx_setproctitle(title);
141
142
143 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
144
145 ngx_start_worker_processes(cycle, ccf->worker_processes,
146 NGX_PROCESS_RESPAWN);
147 ngx_start_cache_manager_processes(cycle, 0);
148
149 ngx_new_binary = 0;
150 delay = 0;
151 sigio = 0;
152 live = 1;
153
154 for ( ;; ) {
155 if (delay) {
156 if (ngx_sigalrm) {
157 sigio = 0;
158 delay *= 2;
159 ngx_sigalrm = 0;
160 }
161
162 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
163 "termination cycle: %M", delay);
164
165 itv.it_interval.tv_sec = 0;
166 itv.it_interval.tv_usec = 0;
167 itv.it_value.tv_sec = delay / 1000;
168 itv.it_value.tv_usec = (delay % 1000 ) * 1000;
169
170 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
171 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
172 "setitimer() failed");
173 }
174 }
175
176 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");
177
178 sigsuspend(&set);
179
180 ngx_time_update();
181
182 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
183 "wake up, sigio %i", sigio);
184
185 if (ngx_reap) {
186 ngx_reap = 0;
187 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");
188
189 live = ngx_reap_children(cycle);
190 }
191
192 if (!live && (ngx_terminate || ngx_quit)) {
193 ngx_master_process_exit(cycle);
194 }
195
196 if (ngx_terminate) {
197 if (delay == 0) {
198 delay = 50;
199 }
200
201 if (sigio) {
202 sigio--;
203 continue;
204 }
205
206 sigio = ccf->worker_processes + 2 /* cache processes */;
207
208 if (delay > 1000) {
209 ngx_signal_worker_processes(cycle, SIGKILL);
210 } else {
211 ngx_signal_worker_processes(cycle,
212 ngx_signal_value(NGX_TERMINATE_SIGNAL));
213 }
214
215 continue;
216 }
217
218 if (ngx_quit) {
219 ngx_signal_worker_processes(cycle,
220 ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
221
222 #if (!NGX_HAVE_FSTACK)
223 ls = cycle->listening.elts;
224 for (n = 0; n < cycle->listening.nelts; n++) {
225 if (ngx_close_socket(ls[n].fd) == -1) {
226 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
227 ngx_close_socket_n " %V failed",
228 &ls[n].addr_text);
229 }
230 }
231 cycle->listening.nelts = 0;
232 #endif
233 continue;
234 }
235
236 if (ngx_reconfigure) {
237 #if (NGX_HAVE_FSTACK)
238 if (!sig_worker_quit) {
239 sig_worker_quit = 1;
240 ngx_signal_worker_processes(cycle,
241 ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
242 continue;
243 }
244
245 if (live) {
246 continue;
247 }
248
249 sig_worker_quit = 0;
250 #endif
251 ngx_reconfigure = 0;
252
253 if (ngx_new_binary) {
254 ngx_start_worker_processes(cycle, ccf->worker_processes,
255 NGX_PROCESS_RESPAWN);
256 ngx_start_cache_manager_processes(cycle, 0);
257 ngx_noaccepting = 0;
258
259 continue;
260 }
261
262 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
263
264 cycle = ngx_init_cycle(cycle);
265 if (cycle == NULL) {
266 cycle = (ngx_cycle_t *) ngx_cycle;
267 continue;
268 }
269
270 ngx_cycle = cycle;
271 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
272 ngx_core_module);
273 ngx_start_worker_processes(cycle, ccf->worker_processes,
274 NGX_PROCESS_JUST_RESPAWN);
275 ngx_start_cache_manager_processes(cycle, 1);
276
277 /* allow new processes to start */
278 ngx_msleep(100);
279
280 live = 1;
281 ngx_signal_worker_processes(cycle,
282 ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
283 }
284
285 if (ngx_restart) {
286 ngx_restart = 0;
287 ngx_start_worker_processes(cycle, ccf->worker_processes,
288 NGX_PROCESS_RESPAWN);
289 ngx_start_cache_manager_processes(cycle, 0);
290 live = 1;
291 }
292
293 if (ngx_reopen) {
294 ngx_reopen = 0;
295 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
296 ngx_reopen_files(cycle, ccf->user);
297 ngx_signal_worker_processes(cycle,
298 ngx_signal_value(NGX_REOPEN_SIGNAL));
299 }
300
301 if (ngx_change_binary) {
302 ngx_change_binary = 0;
303 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
304 ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv);
305 }
306
307 if (ngx_noaccept) {
308 ngx_noaccept = 0;
309 ngx_noaccepting = 1;
310 ngx_signal_worker_processes(cycle,
311 ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
312 }
313 }
314 }
315
316 #if (NGX_HAVE_FSTACK)
317 static int
ngx_single_process_cycle_loop(void * arg)318 ngx_single_process_cycle_loop(void *arg)
319 {
320 ngx_uint_t i;
321 ngx_cycle_t *cycle = (ngx_cycle_t *)arg;
322
323 //ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
324
325 ngx_process_events_and_timers(cycle);
326
327 if (ngx_terminate || ngx_quit) {
328
329 for (i = 0; cycle->modules[i]; i++) {
330 if (cycle->modules[i]->exit_process) {
331 cycle->modules[i]->exit_process(cycle);
332 }
333 }
334
335 ngx_master_process_exit(cycle);
336 }
337
338 if (ngx_reconfigure) {
339 ngx_reconfigure = 0;
340 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
341
342 cycle = ngx_init_cycle(cycle);
343 if (cycle == NULL) {
344 cycle = (ngx_cycle_t *) ngx_cycle;
345 return 0;
346 }
347
348 ngx_cycle = cycle;
349 }
350
351 if (ngx_reopen) {
352 ngx_reopen = 0;
353 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
354 ngx_reopen_files(cycle, (ngx_uid_t) -1);
355 }
356
357 return 0;
358 }
359 #endif
360
361 void
ngx_single_process_cycle(ngx_cycle_t * cycle)362 ngx_single_process_cycle(ngx_cycle_t *cycle)
363 {
364 ngx_uint_t i;
365
366 if (ngx_set_environment(cycle, NULL) == NULL) {
367 /* fatal */
368 exit(2);
369 }
370
371 #if (NGX_HAVE_FSTACK)
372 ngx_core_conf_t *ccf;
373 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
374 if (ccf->fstack_conf.len == 0) {
375 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
376 "fstack_conf null");
377 exit(2);
378 }
379
380 ngx_ff_process = NGX_FF_PROCESS_PRIMARY;
381
382 if (ff_mod_init((const char *)ccf->fstack_conf.data, 0,
383 ngx_ff_process == NGX_FF_PROCESS_PRIMARY)) {
384 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
385 "ff_mod_init failed");
386 exit(2);
387 }
388
389 if (ngx_open_listening_sockets(cycle) != NGX_OK) {
390 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
391 "ngx_open_listening_sockets failed");
392 exit(2);
393 }
394
395 if (!ngx_test_config) {
396 ngx_configure_listening_sockets(cycle);
397 }
398 #endif
399
400 for (i = 0; cycle->modules[i]; i++) {
401 if (cycle->modules[i]->init_process) {
402 if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
403 /* fatal */
404 exit(2);
405 }
406 }
407 }
408
409 #if (NGX_HAVE_FSTACK)
410 ff_run(ngx_single_process_cycle_loop, (void *)cycle);
411 #else
412 for ( ;; ) {
413 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
414
415 ngx_process_events_and_timers(cycle);
416
417 if (ngx_terminate || ngx_quit) {
418
419 for (i = 0; cycle->modules[i]; i++) {
420 if (cycle->modules[i]->exit_process) {
421 cycle->modules[i]->exit_process(cycle);
422 }
423 }
424
425 ngx_master_process_exit(cycle);
426 }
427
428 if (ngx_reconfigure) {
429 ngx_reconfigure = 0;
430 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
431
432 cycle = ngx_init_cycle(cycle);
433 if (cycle == NULL) {
434 cycle = (ngx_cycle_t *) ngx_cycle;
435 continue;
436 }
437
438 ngx_cycle = cycle;
439 }
440
441 if (ngx_reopen) {
442 ngx_reopen = 0;
443 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
444 ngx_reopen_files(cycle, (ngx_uid_t) -1);
445 }
446 }
447 #endif
448 }
449
450
451 static void
ngx_start_worker_processes(ngx_cycle_t * cycle,ngx_int_t n,ngx_int_t type)452 ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
453 {
454 ngx_int_t i;
455 ngx_channel_t ch;
456
457 #if (NGX_HAVE_FSTACK)
458 const char *shm_name = "ff_shm";
459 int shm_fd, r;
460
461 shm_fd = shm_open(shm_name, O_CREAT|O_TRUNC|O_RDWR, 0666);
462 if (shm_fd == -1) {
463 ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
464 "start worker processes shm_open");
465 exit(2);
466 }
467 r = ftruncate(shm_fd, sizeof(sem_t));
468 if (r == -1) {
469 ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
470 "start worker processes ftruncate");
471 exit(2);
472 }
473 ngx_ff_worker_sem = (sem_t *) mmap(NULL, sizeof(sem_t),
474 PROT_READ|PROT_WRITE,MAP_SHARED, shm_fd, 0);
475 if (ngx_ff_worker_sem == MAP_FAILED) {
476 ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
477 "start worker processes mmap");
478 shm_unlink(shm_name);
479 exit(2);
480 }
481 if (sem_init(ngx_ff_worker_sem, 1, 0) != 0)
482 {
483 ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
484 "start worker processes sem_init");
485
486 munmap(ngx_ff_worker_sem, sizeof(sem_t));
487 shm_unlink(shm_name);
488 exit(2);
489 }
490 #endif
491
492 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
493
494 ngx_memzero(&ch, sizeof(ngx_channel_t));
495
496 ch.command = NGX_CMD_OPEN_CHANNEL;
497
498 for (i = 0; i < n; i++) {
499
500 ngx_spawn_process(cycle, ngx_worker_process_cycle,
501 (void *) (intptr_t) i, "worker process", type);
502
503 ch.pid = ngx_processes[ngx_process_slot].pid;
504 ch.slot = ngx_process_slot;
505 ch.fd = ngx_processes[ngx_process_slot].channel[0];
506
507 ngx_pass_open_channel(cycle, &ch);
508
509 #if (NGX_HAVE_FSTACK)
510
511 // wait for ff_primary worker process startup.
512 if (i == 0) {
513 struct timespec ts;
514 (void) clock_gettime(CLOCK_REALTIME,&ts);
515
516 ts.tv_sec += 15; //15s
517 while ((r = sem_timedwait(ngx_ff_worker_sem, &ts)) == -1
518 && errno == EINTR)
519 {
520 continue; /* Restart if interrupted by signal handler */
521 }
522
523 if (r == -1) {
524 ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
525 "primary worker process failed to initialize");
526 exit(2);
527 }
528
529 sem_destroy(ngx_ff_worker_sem);
530 munmap(ngx_ff_worker_sem, sizeof(sem_t));
531 shm_unlink(shm_name);
532 }
533 #endif
534 }
535 }
536
537
538 static void
ngx_start_cache_manager_processes(ngx_cycle_t * cycle,ngx_uint_t respawn)539 ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
540 {
541 ngx_uint_t i, manager, loader;
542 ngx_path_t **path;
543 ngx_channel_t ch;
544
545 manager = 0;
546 loader = 0;
547
548 path = ngx_cycle->paths.elts;
549 for (i = 0; i < ngx_cycle->paths.nelts; i++) {
550
551 if (path[i]->manager) {
552 manager = 1;
553 }
554
555 if (path[i]->loader) {
556 loader = 1;
557 }
558 }
559
560 if (manager == 0) {
561 return;
562 }
563
564 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
565 &ngx_cache_manager_ctx, "cache manager process",
566 respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);
567
568 ngx_memzero(&ch, sizeof(ngx_channel_t));
569
570 ch.command = NGX_CMD_OPEN_CHANNEL;
571 ch.pid = ngx_processes[ngx_process_slot].pid;
572 ch.slot = ngx_process_slot;
573 ch.fd = ngx_processes[ngx_process_slot].channel[0];
574
575 ngx_pass_open_channel(cycle, &ch);
576
577 if (loader == 0) {
578 return;
579 }
580
581 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
582 &ngx_cache_loader_ctx, "cache loader process",
583 respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);
584
585 ch.command = NGX_CMD_OPEN_CHANNEL;
586 ch.pid = ngx_processes[ngx_process_slot].pid;
587 ch.slot = ngx_process_slot;
588 ch.fd = ngx_processes[ngx_process_slot].channel[0];
589
590 ngx_pass_open_channel(cycle, &ch);
591 }
592
593
594 static void
ngx_pass_open_channel(ngx_cycle_t * cycle,ngx_channel_t * ch)595 ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
596 {
597 ngx_int_t i;
598
599 for (i = 0; i < ngx_last_process; i++) {
600
601 if (i == ngx_process_slot
602 || ngx_processes[i].pid == -1
603 || ngx_processes[i].channel[0] == -1)
604 {
605 continue;
606 }
607
608 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
609 "pass channel s:%i pid:%P fd:%d to s:%i pid:%P fd:%d",
610 ch->slot, ch->pid, ch->fd,
611 i, ngx_processes[i].pid,
612 ngx_processes[i].channel[0]);
613
614 /* TODO: NGX_AGAIN */
615
616 ngx_write_channel(ngx_processes[i].channel[0],
617 ch, sizeof(ngx_channel_t), cycle->log);
618 }
619 }
620
621
622 static void
ngx_signal_worker_processes(ngx_cycle_t * cycle,int signo)623 ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
624 {
625 ngx_int_t i;
626 ngx_err_t err;
627 ngx_channel_t ch;
628
629 ngx_memzero(&ch, sizeof(ngx_channel_t));
630
631 #if (NGX_BROKEN_SCM_RIGHTS)
632
633 ch.command = 0;
634
635 #else
636
637 switch (signo) {
638
639 case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
640 ch.command = NGX_CMD_QUIT;
641 break;
642
643 case ngx_signal_value(NGX_TERMINATE_SIGNAL):
644 ch.command = NGX_CMD_TERMINATE;
645 break;
646
647 case ngx_signal_value(NGX_REOPEN_SIGNAL):
648 ch.command = NGX_CMD_REOPEN;
649 break;
650
651 default:
652 ch.command = 0;
653 }
654
655 #endif
656
657 ch.fd = -1;
658
659
660 for (i = 0; i < ngx_last_process; i++) {
661
662 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
663 "child: %i %P e:%d t:%d d:%d r:%d j:%d",
664 i,
665 ngx_processes[i].pid,
666 ngx_processes[i].exiting,
667 ngx_processes[i].exited,
668 ngx_processes[i].detached,
669 ngx_processes[i].respawn,
670 ngx_processes[i].just_spawn);
671
672 if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
673 continue;
674 }
675
676 if (ngx_processes[i].just_spawn) {
677 ngx_processes[i].just_spawn = 0;
678 continue;
679 }
680
681 if (ngx_processes[i].exiting
682 && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL))
683 {
684 continue;
685 }
686
687 if (ch.command) {
688 if (ngx_write_channel(ngx_processes[i].channel[0],
689 &ch, sizeof(ngx_channel_t), cycle->log)
690 == NGX_OK)
691 {
692 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
693 ngx_processes[i].exiting = 1;
694 }
695
696 continue;
697 }
698 }
699
700 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
701 "kill (%P, %d)", ngx_processes[i].pid, signo);
702
703 if (kill(ngx_processes[i].pid, signo) == -1) {
704 err = ngx_errno;
705 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
706 "kill(%P, %d) failed", ngx_processes[i].pid, signo);
707
708 if (err == NGX_ESRCH) {
709 ngx_processes[i].exited = 1;
710 ngx_processes[i].exiting = 0;
711 ngx_reap = 1;
712 }
713
714 continue;
715 }
716
717 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
718 ngx_processes[i].exiting = 1;
719 }
720 }
721 }
722
723
724 static ngx_uint_t
ngx_reap_children(ngx_cycle_t * cycle)725 ngx_reap_children(ngx_cycle_t *cycle)
726 {
727 ngx_int_t i, n;
728 ngx_uint_t live;
729 ngx_channel_t ch;
730 ngx_core_conf_t *ccf;
731
732 ngx_memzero(&ch, sizeof(ngx_channel_t));
733
734 ch.command = NGX_CMD_CLOSE_CHANNEL;
735 ch.fd = -1;
736
737 live = 0;
738 for (i = 0; i < ngx_last_process; i++) {
739
740 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
741 "child: %i %P e:%d t:%d d:%d r:%d j:%d",
742 i,
743 ngx_processes[i].pid,
744 ngx_processes[i].exiting,
745 ngx_processes[i].exited,
746 ngx_processes[i].detached,
747 ngx_processes[i].respawn,
748 ngx_processes[i].just_spawn);
749
750 if (ngx_processes[i].pid == -1) {
751 continue;
752 }
753
754 if (ngx_processes[i].exited) {
755
756 if (!ngx_processes[i].detached) {
757 ngx_close_channel(ngx_processes[i].channel, cycle->log);
758
759 ngx_processes[i].channel[0] = -1;
760 ngx_processes[i].channel[1] = -1;
761
762 ch.pid = ngx_processes[i].pid;
763 ch.slot = i;
764
765 for (n = 0; n < ngx_last_process; n++) {
766 if (ngx_processes[n].exited
767 || ngx_processes[n].pid == -1
768 || ngx_processes[n].channel[0] == -1)
769 {
770 continue;
771 }
772
773 ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0,
774 "pass close channel s:%i pid:%P to:%P",
775 ch.slot, ch.pid, ngx_processes[n].pid);
776
777 /* TODO: NGX_AGAIN */
778
779 ngx_write_channel(ngx_processes[n].channel[0],
780 &ch, sizeof(ngx_channel_t), cycle->log);
781 }
782 }
783
784 if (ngx_processes[i].respawn
785 && !ngx_processes[i].exiting
786 && !ngx_terminate
787 && !ngx_quit
788 #if (NGX_HAVE_FSTACK)
789 && !ngx_reconfigure
790 #endif
791 )
792 {
793 if (ngx_spawn_process(cycle, ngx_processes[i].proc,
794 ngx_processes[i].data,
795 ngx_processes[i].name, i)
796 == NGX_INVALID_PID)
797 {
798 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
799 "could not respawn %s",
800 ngx_processes[i].name);
801 continue;
802 }
803
804
805 ch.command = NGX_CMD_OPEN_CHANNEL;
806 ch.pid = ngx_processes[ngx_process_slot].pid;
807 ch.slot = ngx_process_slot;
808 ch.fd = ngx_processes[ngx_process_slot].channel[0];
809
810 ngx_pass_open_channel(cycle, &ch);
811
812 live = 1;
813
814 continue;
815 }
816
817 if (ngx_processes[i].pid == ngx_new_binary) {
818
819 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
820 ngx_core_module);
821
822 if (ngx_rename_file((char *) ccf->oldpid.data,
823 (char *) ccf->pid.data)
824 == NGX_FILE_ERROR)
825 {
826 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
827 ngx_rename_file_n " %s back to %s failed "
828 "after the new binary process \"%s\" exited",
829 ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
830 }
831
832 ngx_new_binary = 0;
833 if (ngx_noaccepting) {
834 ngx_restart = 1;
835 ngx_noaccepting = 0;
836 }
837 }
838
839 if (i == ngx_last_process - 1) {
840 ngx_last_process--;
841
842 } else {
843 ngx_processes[i].pid = -1;
844 }
845
846 } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
847 live = 1;
848 }
849 }
850
851 return live;
852 }
853
854
855 static void
ngx_master_process_exit(ngx_cycle_t * cycle)856 ngx_master_process_exit(ngx_cycle_t *cycle)
857 {
858 ngx_uint_t i;
859
860 ngx_delete_pidfile(cycle);
861
862 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
863
864 for (i = 0; cycle->modules[i]; i++) {
865 if (cycle->modules[i]->exit_master) {
866 cycle->modules[i]->exit_master(cycle);
867 }
868 }
869
870 ngx_close_listening_sockets(cycle);
871
872 /*
873 * Copy ngx_cycle->log related data to the special static exit cycle,
874 * log, and log file structures enough to allow a signal handler to log.
875 * The handler may be called when standard ngx_cycle->log allocated from
876 * ngx_cycle->pool is already destroyed.
877 */
878
879
880 ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log);
881
882 ngx_exit_log_file.fd = ngx_exit_log.file->fd;
883 ngx_exit_log.file = &ngx_exit_log_file;
884 ngx_exit_log.next = NULL;
885 ngx_exit_log.writer = NULL;
886
887 ngx_exit_cycle.log = &ngx_exit_log;
888 ngx_exit_cycle.files = ngx_cycle->files;
889 ngx_exit_cycle.files_n = ngx_cycle->files_n;
890 ngx_cycle = &ngx_exit_cycle;
891
892 ngx_destroy_pool(cycle->pool);
893
894 exit(0);
895 }
896
897 #if (NGX_HAVE_FSTACK)
898 static int
ngx_worker_process_cycle_loop(void * arg)899 ngx_worker_process_cycle_loop(void *arg)
900 {
901 ngx_cycle_t *cycle = (ngx_cycle_t *)arg;
902
903 if (ngx_exiting) {
904 if (ngx_event_no_timers_left() == NGX_OK) {
905 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
906 ngx_worker_process_exit(cycle);
907 }
908 }
909
910 //ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
911
912 ngx_process_events_and_timers(cycle);
913
914 if (ngx_terminate) {
915 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
916 ngx_worker_process_exit(cycle);
917 }
918
919 if (ngx_quit) {
920 ngx_quit = 0;
921 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
922 "gracefully shutting down");
923 ngx_setproctitle("worker process is shutting down");
924
925 if (!ngx_exiting) {
926 ngx_exiting = 1;
927 ngx_close_listening_sockets(cycle);
928 ngx_close_idle_connections(cycle);
929 }
930 }
931
932 if (ngx_reopen) {
933 ngx_reopen = 0;
934 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
935 ngx_reopen_files(cycle, -1);
936 }
937
938 return 0;
939 }
940 #endif
941
942 static void
ngx_worker_process_cycle(ngx_cycle_t * cycle,void * data)943 ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
944 {
945 ngx_int_t worker = (intptr_t) data;
946
947 ngx_process = NGX_PROCESS_WORKER;
948 ngx_worker = worker;
949
950 ngx_worker_process_init(cycle, worker);
951
952 ngx_setproctitle("worker process");
953
954 #if (NGX_HAVE_FSTACK)
955 ff_run(ngx_worker_process_cycle_loop, (void *)cycle);
956 #else
957
958 for ( ;; ) {
959
960 if (ngx_exiting) {
961 if (ngx_event_no_timers_left() == NGX_OK) {
962 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
963 ngx_worker_process_exit(cycle);
964 }
965 }
966
967 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
968
969 ngx_process_events_and_timers(cycle);
970
971 if (ngx_terminate) {
972 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
973 ngx_worker_process_exit(cycle);
974 }
975
976 if (ngx_quit) {
977 ngx_quit = 0;
978 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
979 "gracefully shutting down");
980 ngx_setproctitle("worker process is shutting down");
981
982 if (!ngx_exiting) {
983 ngx_exiting = 1;
984 ngx_set_shutdown_timer(cycle);
985 ngx_close_listening_sockets(cycle);
986 ngx_close_idle_connections(cycle);
987 }
988 }
989
990 if (ngx_reopen) {
991 ngx_reopen = 0;
992 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
993 ngx_reopen_files(cycle, -1);
994 }
995 }
996 #endif
997 }
998
999
1000 static void
ngx_worker_process_init(ngx_cycle_t * cycle,ngx_int_t worker)1001 ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
1002 {
1003 sigset_t set;
1004 ngx_int_t n;
1005 ngx_time_t *tp;
1006 ngx_uint_t i;
1007 ngx_cpuset_t *cpu_affinity;
1008 struct rlimit rlmt;
1009 ngx_core_conf_t *ccf;
1010 ngx_listening_t *ls;
1011
1012 if (ngx_set_environment(cycle, NULL) == NULL) {
1013 /* fatal */
1014 exit(2);
1015 }
1016
1017 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
1018
1019 if (worker >= 0 && ccf->priority != 0) {
1020 if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
1021 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1022 "setpriority(%d) failed", ccf->priority);
1023 }
1024 }
1025
1026 if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
1027 rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
1028 rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
1029
1030 if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
1031 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1032 "setrlimit(RLIMIT_NOFILE, %i) failed",
1033 ccf->rlimit_nofile);
1034 }
1035 }
1036
1037 if (ccf->rlimit_core != NGX_CONF_UNSET) {
1038 rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
1039 rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
1040
1041 if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
1042 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1043 "setrlimit(RLIMIT_CORE, %O) failed",
1044 ccf->rlimit_core);
1045 }
1046 }
1047
1048 if (geteuid() == 0) {
1049 if (setgid(ccf->group) == -1) {
1050 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1051 "setgid(%d) failed", ccf->group);
1052 /* fatal */
1053 exit(2);
1054 }
1055
1056 if (initgroups(ccf->username, ccf->group) == -1) {
1057 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1058 "initgroups(%s, %d) failed",
1059 ccf->username, ccf->group);
1060 }
1061
1062 #if (NGX_HAVE_PR_SET_KEEPCAPS && NGX_HAVE_CAPABILITIES)
1063 if (ccf->transparent && ccf->user) {
1064 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
1065 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1066 "prctl(PR_SET_KEEPCAPS, 1) failed");
1067 /* fatal */
1068 exit(2);
1069 }
1070 }
1071 #endif
1072
1073 if (setuid(ccf->user) == -1) {
1074 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1075 "setuid(%d) failed", ccf->user);
1076 /* fatal */
1077 exit(2);
1078 }
1079
1080 #if (NGX_HAVE_CAPABILITIES)
1081 if (ccf->transparent && ccf->user) {
1082 struct __user_cap_data_struct data;
1083 struct __user_cap_header_struct header;
1084
1085 ngx_memzero(&header, sizeof(struct __user_cap_header_struct));
1086 ngx_memzero(&data, sizeof(struct __user_cap_data_struct));
1087
1088 header.version = _LINUX_CAPABILITY_VERSION_1;
1089 data.effective = CAP_TO_MASK(CAP_NET_RAW);
1090 data.permitted = data.effective;
1091
1092 if (syscall(SYS_capset, &header, &data) == -1) {
1093 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1094 "capset() failed");
1095 /* fatal */
1096 exit(2);
1097 }
1098 }
1099 #endif
1100 }
1101
1102 if (worker >= 0) {
1103 cpu_affinity = ngx_get_cpu_affinity(worker);
1104
1105 if (cpu_affinity) {
1106 ngx_setaffinity(cpu_affinity, cycle->log);
1107 }
1108 }
1109
1110 #if (NGX_HAVE_PR_SET_DUMPABLE)
1111
1112 /* allow coredump after setuid() in Linux 2.4.x */
1113
1114 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
1115 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1116 "prctl(PR_SET_DUMPABLE) failed");
1117 }
1118
1119 #endif
1120
1121 if (ccf->working_directory.len) {
1122 if (chdir((char *) ccf->working_directory.data) == -1) {
1123 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1124 "chdir(\"%s\") failed", ccf->working_directory.data);
1125 /* fatal */
1126 exit(2);
1127 }
1128 }
1129
1130 sigemptyset(&set);
1131
1132 if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
1133 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1134 "sigprocmask() failed");
1135 }
1136
1137 tp = ngx_timeofday();
1138 srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);
1139
1140 #if (NGX_HAVE_FSTACK)
1141 if (worker >= 0) {
1142 if (ccf->fstack_conf.len == 0) {
1143 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
1144 "fstack_conf null");
1145 exit(2);
1146 }
1147
1148 if (worker == 0) {
1149 ngx_ff_process = NGX_FF_PROCESS_PRIMARY;
1150 } else {
1151 ngx_ff_process = NGX_FF_PROCESS_SECONDARY;
1152 }
1153
1154 if (ff_mod_init((const char *)ccf->fstack_conf.data, worker,
1155 ngx_ff_process == NGX_FF_PROCESS_PRIMARY)) {
1156 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
1157 "ff_mod_init failed");
1158 exit(2);
1159 }
1160
1161 if (worker == 0) {
1162 (void) sem_post(ngx_ff_worker_sem);
1163 }
1164
1165 if (ngx_open_listening_sockets(cycle) != NGX_OK) {
1166 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1167 "ngx_open_listening_sockets failed");
1168 exit(2);
1169 }
1170
1171 if (!ngx_test_config) {
1172 ngx_configure_listening_sockets(cycle);
1173 }
1174 }
1175 #endif
1176
1177 /*
1178 * disable deleting previous events for the listening sockets because
1179 * in the worker processes there are no events at all at this point
1180 */
1181 ls = cycle->listening.elts;
1182 for (i = 0; i < cycle->listening.nelts; i++) {
1183 ls[i].previous = NULL;
1184 }
1185
1186 for (i = 0; cycle->modules[i]; i++) {
1187 if (cycle->modules[i]->init_process) {
1188 if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
1189 /* fatal */
1190 exit(2);
1191 }
1192 }
1193 }
1194
1195 for (n = 0; n < ngx_last_process; n++) {
1196
1197 if (ngx_processes[n].pid == -1) {
1198 continue;
1199 }
1200
1201 if (n == ngx_process_slot) {
1202 continue;
1203 }
1204
1205 if (ngx_processes[n].channel[1] == -1) {
1206 continue;
1207 }
1208
1209 if (close(ngx_processes[n].channel[1]) == -1) {
1210 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1211 "close() channel failed");
1212 }
1213 }
1214
1215 if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
1216 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
1217 "close() channel failed");
1218 }
1219
1220 #if 0
1221 ngx_last_process = 0;
1222 #endif
1223
1224 if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
1225 ngx_channel_handler)
1226 == NGX_ERROR)
1227 {
1228 /* fatal */
1229 exit(2);
1230 }
1231 }
1232
1233
1234 static void
ngx_worker_process_exit(ngx_cycle_t * cycle)1235 ngx_worker_process_exit(ngx_cycle_t *cycle)
1236 {
1237 ngx_uint_t i;
1238 ngx_connection_t *c;
1239
1240 for (i = 0; cycle->modules[i]; i++) {
1241 if (cycle->modules[i]->exit_process) {
1242 cycle->modules[i]->exit_process(cycle);
1243 }
1244 }
1245
1246 if (ngx_exiting) {
1247 c = cycle->connections;
1248 for (i = 0; i < cycle->connection_n; i++) {
1249 if (c[i].fd != -1
1250 && c[i].read
1251 && !c[i].read->accept
1252 && !c[i].read->channel
1253 && !c[i].read->resolver)
1254 {
1255 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
1256 "*%uA open socket #%d left in connection %ui",
1257 c[i].number, c[i].fd, i);
1258 ngx_debug_quit = 1;
1259 }
1260 }
1261
1262 if (ngx_debug_quit) {
1263 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
1264 ngx_debug_point();
1265 }
1266 }
1267
1268 /*
1269 * Copy ngx_cycle->log related data to the special static exit cycle,
1270 * log, and log file structures enough to allow a signal handler to log.
1271 * The handler may be called when standard ngx_cycle->log allocated from
1272 * ngx_cycle->pool is already destroyed.
1273 */
1274
1275 ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log);
1276
1277 ngx_exit_log_file.fd = ngx_exit_log.file->fd;
1278 ngx_exit_log.file = &ngx_exit_log_file;
1279 ngx_exit_log.next = NULL;
1280 ngx_exit_log.writer = NULL;
1281
1282 ngx_exit_cycle.log = &ngx_exit_log;
1283 ngx_exit_cycle.files = ngx_cycle->files;
1284 ngx_exit_cycle.files_n = ngx_cycle->files_n;
1285 ngx_cycle = &ngx_exit_cycle;
1286
1287 ngx_destroy_pool(cycle->pool);
1288
1289 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit");
1290
1291 #if (NGX_HAVE_FSTACK)
1292 if (ngx_ff_process == NGX_FF_PROCESS_PRIMARY) {
1293 // wait for secondary worker processes to exit.
1294 ngx_msleep(500);
1295 }
1296 #endif
1297
1298 exit(0);
1299 }
1300
1301
1302 static void
ngx_channel_handler(ngx_event_t * ev)1303 ngx_channel_handler(ngx_event_t *ev)
1304 {
1305 ngx_int_t n;
1306 ngx_channel_t ch;
1307 ngx_connection_t *c;
1308
1309 if (ev->timedout) {
1310 ev->timedout = 0;
1311 return;
1312 }
1313
1314 c = ev->data;
1315
1316 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");
1317
1318 for ( ;; ) {
1319
1320 n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
1321
1322 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
1323
1324 if (n == NGX_ERROR) {
1325
1326 if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
1327 ngx_del_conn(c, 0);
1328 }
1329
1330 ngx_close_connection(c);
1331 return;
1332 }
1333
1334 if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
1335 if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
1336 return;
1337 }
1338 }
1339
1340 if (n == NGX_AGAIN) {
1341 return;
1342 }
1343
1344 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
1345 "channel command: %ui", ch.command);
1346
1347 switch (ch.command) {
1348
1349 case NGX_CMD_QUIT:
1350 ngx_quit = 1;
1351 break;
1352
1353 case NGX_CMD_TERMINATE:
1354 ngx_terminate = 1;
1355 break;
1356
1357 case NGX_CMD_REOPEN:
1358 ngx_reopen = 1;
1359 break;
1360
1361 case NGX_CMD_OPEN_CHANNEL:
1362
1363 ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,
1364 "get channel s:%i pid:%P fd:%d",
1365 ch.slot, ch.pid, ch.fd);
1366
1367 ngx_processes[ch.slot].pid = ch.pid;
1368 ngx_processes[ch.slot].channel[0] = ch.fd;
1369 break;
1370
1371 case NGX_CMD_CLOSE_CHANNEL:
1372
1373 ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,
1374 "close channel s:%i pid:%P our:%P fd:%d",
1375 ch.slot, ch.pid, ngx_processes[ch.slot].pid,
1376 ngx_processes[ch.slot].channel[0]);
1377
1378 if (close(ngx_processes[ch.slot].channel[0]) == -1) {
1379 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
1380 "close() channel failed");
1381 }
1382
1383 ngx_processes[ch.slot].channel[0] = -1;
1384 break;
1385 }
1386 }
1387 }
1388
1389
1390 static void
ngx_cache_manager_process_cycle(ngx_cycle_t * cycle,void * data)1391 ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
1392 {
1393 ngx_cache_manager_ctx_t *ctx = data;
1394
1395 void *ident[4];
1396 ngx_event_t ev;
1397
1398 /*
1399 * Set correct process type since closing listening Unix domain socket
1400 * in a master process also removes the Unix domain socket file.
1401 */
1402 ngx_process = NGX_PROCESS_HELPER;
1403
1404 ngx_close_listening_sockets(cycle);
1405
1406 /* Set a moderate number of connections for a helper process. */
1407 cycle->connection_n = 512;
1408
1409 ngx_worker_process_init(cycle, -1);
1410
1411 ngx_memzero(&ev, sizeof(ngx_event_t));
1412 ev.handler = ctx->handler;
1413 ev.data = ident;
1414 ev.log = cycle->log;
1415 ident[3] = (void *) -1;
1416
1417 ngx_use_accept_mutex = 0;
1418
1419 ngx_setproctitle(ctx->name);
1420
1421 ngx_add_timer(&ev, ctx->delay);
1422
1423 for ( ;; ) {
1424
1425 if (ngx_terminate || ngx_quit) {
1426 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
1427 exit(0);
1428 }
1429
1430 if (ngx_reopen) {
1431 ngx_reopen = 0;
1432 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
1433 ngx_reopen_files(cycle, -1);
1434 }
1435
1436 ngx_process_events_and_timers(cycle);
1437 }
1438 }
1439
1440
1441 static void
ngx_cache_manager_process_handler(ngx_event_t * ev)1442 ngx_cache_manager_process_handler(ngx_event_t *ev)
1443 {
1444 ngx_uint_t i;
1445 ngx_msec_t next, n;
1446 ngx_path_t **path;
1447
1448 next = 60 * 60 * 1000;
1449
1450 path = ngx_cycle->paths.elts;
1451 for (i = 0; i < ngx_cycle->paths.nelts; i++) {
1452
1453 if (path[i]->manager) {
1454 n = path[i]->manager(path[i]->data);
1455
1456 next = (n <= next) ? n : next;
1457
1458 ngx_time_update();
1459 }
1460 }
1461
1462 if (next == 0) {
1463 next = 1;
1464 }
1465
1466 ngx_add_timer(ev, next);
1467 }
1468
1469
1470 static void
ngx_cache_loader_process_handler(ngx_event_t * ev)1471 ngx_cache_loader_process_handler(ngx_event_t *ev)
1472 {
1473 ngx_uint_t i;
1474 ngx_path_t **path;
1475 ngx_cycle_t *cycle;
1476
1477 cycle = (ngx_cycle_t *) ngx_cycle;
1478
1479 path = cycle->paths.elts;
1480 for (i = 0; i < cycle->paths.nelts; i++) {
1481
1482 if (ngx_terminate || ngx_quit) {
1483 break;
1484 }
1485
1486 if (path[i]->loader) {
1487 path[i]->loader(path[i]->data);
1488 ngx_time_update();
1489 }
1490 }
1491
1492 exit(0);
1493 }
1494