Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.19.2 ]​[ nginx-1.18.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 #include <ngx_channel.h>
0012 
0013 
0014 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
0015     ngx_int_t type);
0016 static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle,
0017     ngx_uint_t respawn);
0018 static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch);
0019 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
0020 static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
0021 static void ngx_master_process_exit(ngx_cycle_t *cycle);
0022 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
0023 static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker);
0024 static void ngx_worker_process_exit(ngx_cycle_t *cycle);
0025 static void ngx_channel_handler(ngx_event_t *ev);
0026 static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data);
0027 static void ngx_cache_manager_process_handler(ngx_event_t *ev);
0028 static void ngx_cache_loader_process_handler(ngx_event_t *ev);
0029 
0030 
0031 ngx_uint_t    ngx_process;
0032 ngx_uint_t    ngx_worker;
0033 ngx_pid_t     ngx_pid;
0034 ngx_pid_t     ngx_parent;
0035 
0036 sig_atomic_t  ngx_reap;
0037 sig_atomic_t  ngx_sigio;
0038 sig_atomic_t  ngx_sigalrm;
0039 sig_atomic_t  ngx_terminate;
0040 sig_atomic_t  ngx_quit;
0041 sig_atomic_t  ngx_debug_quit;
0042 ngx_uint_t    ngx_exiting;
0043 sig_atomic_t  ngx_reconfigure;
0044 sig_atomic_t  ngx_reopen;
0045 
0046 sig_atomic_t  ngx_change_binary;
0047 ngx_pid_t     ngx_new_binary;
0048 ngx_uint_t    ngx_inherited;
0049 ngx_uint_t    ngx_daemonized;
0050 
0051 sig_atomic_t  ngx_noaccept;
0052 ngx_uint_t    ngx_noaccepting;
0053 ngx_uint_t    ngx_restart;
0054 
0055 
0056 static u_char  master_process[] = "master process";
0057 
0058 
0059 static ngx_cache_manager_ctx_t  ngx_cache_manager_ctx = {
0060     ngx_cache_manager_process_handler, "cache manager process", 0
0061 };
0062 
0063 static ngx_cache_manager_ctx_t  ngx_cache_loader_ctx = {
0064     ngx_cache_loader_process_handler, "cache loader process", 60000
0065 };
0066 
0067 
0068 static ngx_cycle_t      ngx_exit_cycle;
0069 static ngx_log_t        ngx_exit_log;
0070 static ngx_open_file_t  ngx_exit_log_file;
0071 
0072 
0073 void
0074 ngx_master_process_cycle(ngx_cycle_t *cycle)
0075 {
0076     char              *title;
0077     u_char            *p;
0078     size_t             size;
0079     ngx_int_t          i;
0080     ngx_uint_t         sigio;
0081     sigset_t           set;
0082     struct itimerval   itv;
0083     ngx_uint_t         live;
0084     ngx_msec_t         delay;
0085     ngx_core_conf_t   *ccf;
0086 
0087     sigemptyset(&set);
0088     sigaddset(&set, SIGCHLD);
0089     sigaddset(&set, SIGALRM);
0090     sigaddset(&set, SIGIO);
0091     sigaddset(&set, SIGINT);
0092     sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
0093     sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
0094     sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
0095     sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
0096     sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
0097     sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
0098 
0099     if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
0100         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0101                       "sigprocmask() failed");
0102     }
0103 
0104     sigemptyset(&set);
0105 
0106 
0107     size = sizeof(master_process);
0108 
0109     for (i = 0; i < ngx_argc; i++) {
0110         size += ngx_strlen(ngx_argv[i]) + 1;
0111     }
0112 
0113     title = ngx_pnalloc(cycle->pool, size);
0114     if (title == NULL) {
0115         /* fatal */
0116         exit(2);
0117     }
0118 
0119     p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);
0120     for (i = 0; i < ngx_argc; i++) {
0121         *p++ = ' ';
0122         p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
0123     }
0124 
0125     ngx_setproctitle(title);
0126 
0127 
0128     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
0129 
0130     ngx_start_worker_processes(cycle, ccf->worker_processes,
0131                                NGX_PROCESS_RESPAWN);
0132     ngx_start_cache_manager_processes(cycle, 0);
0133 
0134     ngx_new_binary = 0;
0135     delay = 0;
0136     sigio = 0;
0137     live = 1;
0138 
0139     for ( ;; ) {
0140         if (delay) {
0141             if (ngx_sigalrm) {
0142                 sigio = 0;
0143                 delay *= 2;
0144                 ngx_sigalrm = 0;
0145             }
0146 
0147             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0148                            "termination cycle: %M", delay);
0149 
0150             itv.it_interval.tv_sec = 0;
0151             itv.it_interval.tv_usec = 0;
0152             itv.it_value.tv_sec = delay / 1000;
0153             itv.it_value.tv_usec = (delay % 1000 ) * 1000;
0154 
0155             if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
0156                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0157                               "setitimer() failed");
0158             }
0159         }
0160 
0161         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");
0162 
0163         sigsuspend(&set);
0164 
0165         ngx_time_update();
0166 
0167         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0168                        "wake up, sigio %i", sigio);
0169 
0170         if (ngx_reap) {
0171             ngx_reap = 0;
0172             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");
0173 
0174             live = ngx_reap_children(cycle);
0175         }
0176 
0177         if (!live && (ngx_terminate || ngx_quit)) {
0178             ngx_master_process_exit(cycle);
0179         }
0180 
0181         if (ngx_terminate) {
0182             if (delay == 0) {
0183                 delay = 50;
0184             }
0185 
0186             if (sigio) {
0187                 sigio--;
0188                 continue;
0189             }
0190 
0191             sigio = ccf->worker_processes + 2 /* cache processes */;
0192 
0193             if (delay > 1000) {
0194                 ngx_signal_worker_processes(cycle, SIGKILL);
0195             } else {
0196                 ngx_signal_worker_processes(cycle,
0197                                        ngx_signal_value(NGX_TERMINATE_SIGNAL));
0198             }
0199 
0200             continue;
0201         }
0202 
0203         if (ngx_quit) {
0204             ngx_signal_worker_processes(cycle,
0205                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
0206             ngx_close_listening_sockets(cycle);
0207 
0208             continue;
0209         }
0210 
0211         if (ngx_reconfigure) {
0212             ngx_reconfigure = 0;
0213 
0214             if (ngx_new_binary) {
0215                 ngx_start_worker_processes(cycle, ccf->worker_processes,
0216                                            NGX_PROCESS_RESPAWN);
0217                 ngx_start_cache_manager_processes(cycle, 0);
0218                 ngx_noaccepting = 0;
0219 
0220                 continue;
0221             }
0222 
0223             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
0224 
0225             cycle = ngx_init_cycle(cycle);
0226             if (cycle == NULL) {
0227                 cycle = (ngx_cycle_t *) ngx_cycle;
0228                 continue;
0229             }
0230 
0231             ngx_cycle = cycle;
0232             ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
0233                                                    ngx_core_module);
0234             ngx_start_worker_processes(cycle, ccf->worker_processes,
0235                                        NGX_PROCESS_JUST_RESPAWN);
0236             ngx_start_cache_manager_processes(cycle, 1);
0237 
0238             /* allow new processes to start */
0239             ngx_msleep(100);
0240 
0241             live = 1;
0242             ngx_signal_worker_processes(cycle,
0243                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
0244         }
0245 
0246         if (ngx_restart) {
0247             ngx_restart = 0;
0248             ngx_start_worker_processes(cycle, ccf->worker_processes,
0249                                        NGX_PROCESS_RESPAWN);
0250             ngx_start_cache_manager_processes(cycle, 0);
0251             live = 1;
0252         }
0253 
0254         if (ngx_reopen) {
0255             ngx_reopen = 0;
0256             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
0257             ngx_reopen_files(cycle, ccf->user);
0258             ngx_signal_worker_processes(cycle,
0259                                         ngx_signal_value(NGX_REOPEN_SIGNAL));
0260         }
0261 
0262         if (ngx_change_binary) {
0263             ngx_change_binary = 0;
0264             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
0265             ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv);
0266         }
0267 
0268         if (ngx_noaccept) {
0269             ngx_noaccept = 0;
0270             ngx_noaccepting = 1;
0271             ngx_signal_worker_processes(cycle,
0272                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
0273         }
0274     }
0275 }
0276 
0277 
0278 void
0279 ngx_single_process_cycle(ngx_cycle_t *cycle)
0280 {
0281     ngx_uint_t  i;
0282 
0283     if (ngx_set_environment(cycle, NULL) == NULL) {
0284         /* fatal */
0285         exit(2);
0286     }
0287 
0288     for (i = 0; cycle->modules[i]; i++) {
0289         if (cycle->modules[i]->init_process) {
0290             if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
0291                 /* fatal */
0292                 exit(2);
0293             }
0294         }
0295     }
0296 
0297     for ( ;; ) {
0298         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
0299 
0300         ngx_process_events_and_timers(cycle);
0301 
0302         if (ngx_terminate || ngx_quit) {
0303 
0304             for (i = 0; cycle->modules[i]; i++) {
0305                 if (cycle->modules[i]->exit_process) {
0306                     cycle->modules[i]->exit_process(cycle);
0307                 }
0308             }
0309 
0310             ngx_master_process_exit(cycle);
0311         }
0312 
0313         if (ngx_reconfigure) {
0314             ngx_reconfigure = 0;
0315             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
0316 
0317             cycle = ngx_init_cycle(cycle);
0318             if (cycle == NULL) {
0319                 cycle = (ngx_cycle_t *) ngx_cycle;
0320                 continue;
0321             }
0322 
0323             ngx_cycle = cycle;
0324         }
0325 
0326         if (ngx_reopen) {
0327             ngx_reopen = 0;
0328             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
0329             ngx_reopen_files(cycle, (ngx_uid_t) -1);
0330         }
0331     }
0332 }
0333 
0334 
0335 static void
0336 ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
0337 {
0338     ngx_int_t      i;
0339     ngx_channel_t  ch;
0340 
0341     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
0342 
0343     ngx_memzero(&ch, sizeof(ngx_channel_t));
0344 
0345     ch.command = NGX_CMD_OPEN_CHANNEL;
0346 
0347     for (i = 0; i < n; i++) {
0348 
0349         ngx_spawn_process(cycle, ngx_worker_process_cycle,
0350                           (void *) (intptr_t) i, "worker process", type);
0351 
0352         ch.pid = ngx_processes[ngx_process_slot].pid;
0353         ch.slot = ngx_process_slot;
0354         ch.fd = ngx_processes[ngx_process_slot].channel[0];
0355 
0356         ngx_pass_open_channel(cycle, &ch);
0357     }
0358 }
0359 
0360 
0361 static void
0362 ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
0363 {
0364     ngx_uint_t       i, manager, loader;
0365     ngx_path_t     **path;
0366     ngx_channel_t    ch;
0367 
0368     manager = 0;
0369     loader = 0;
0370 
0371     path = ngx_cycle->paths.elts;
0372     for (i = 0; i < ngx_cycle->paths.nelts; i++) {
0373 
0374         if (path[i]->manager) {
0375             manager = 1;
0376         }
0377 
0378         if (path[i]->loader) {
0379             loader = 1;
0380         }
0381     }
0382 
0383     if (manager == 0) {
0384         return;
0385     }
0386 
0387     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
0388                       &ngx_cache_manager_ctx, "cache manager process",
0389                       respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);
0390 
0391     ngx_memzero(&ch, sizeof(ngx_channel_t));
0392 
0393     ch.command = NGX_CMD_OPEN_CHANNEL;
0394     ch.pid = ngx_processes[ngx_process_slot].pid;
0395     ch.slot = ngx_process_slot;
0396     ch.fd = ngx_processes[ngx_process_slot].channel[0];
0397 
0398     ngx_pass_open_channel(cycle, &ch);
0399 
0400     if (loader == 0) {
0401         return;
0402     }
0403 
0404     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
0405                       &ngx_cache_loader_ctx, "cache loader process",
0406                       respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);
0407 
0408     ch.command = NGX_CMD_OPEN_CHANNEL;
0409     ch.pid = ngx_processes[ngx_process_slot].pid;
0410     ch.slot = ngx_process_slot;
0411     ch.fd = ngx_processes[ngx_process_slot].channel[0];
0412 
0413     ngx_pass_open_channel(cycle, &ch);
0414 }
0415 
0416 
0417 static void
0418 ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
0419 {
0420     ngx_int_t  i;
0421 
0422     for (i = 0; i < ngx_last_process; i++) {
0423 
0424         if (i == ngx_process_slot
0425             || ngx_processes[i].pid == -1
0426             || ngx_processes[i].channel[0] == -1)
0427         {
0428             continue;
0429         }
0430 
0431         ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
0432                       "pass channel s:%i pid:%P fd:%d to s:%i pid:%P fd:%d",
0433                       ch->slot, ch->pid, ch->fd,
0434                       i, ngx_processes[i].pid,
0435                       ngx_processes[i].channel[0]);
0436 
0437         /* TODO: NGX_AGAIN */
0438 
0439         ngx_write_channel(ngx_processes[i].channel[0],
0440                           ch, sizeof(ngx_channel_t), cycle->log);
0441     }
0442 }
0443 
0444 
0445 static void
0446 ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
0447 {
0448     ngx_int_t      i;
0449     ngx_err_t      err;
0450     ngx_channel_t  ch;
0451 
0452     ngx_memzero(&ch, sizeof(ngx_channel_t));
0453 
0454 #if (NGX_BROKEN_SCM_RIGHTS)
0455 
0456     ch.command = 0;
0457 
0458 #else
0459 
0460     switch (signo) {
0461 
0462     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
0463         ch.command = NGX_CMD_QUIT;
0464         break;
0465 
0466     case ngx_signal_value(NGX_TERMINATE_SIGNAL):
0467         ch.command = NGX_CMD_TERMINATE;
0468         break;
0469 
0470     case ngx_signal_value(NGX_REOPEN_SIGNAL):
0471         ch.command = NGX_CMD_REOPEN;
0472         break;
0473 
0474     default:
0475         ch.command = 0;
0476     }
0477 
0478 #endif
0479 
0480     ch.fd = -1;
0481 
0482 
0483     for (i = 0; i < ngx_last_process; i++) {
0484 
0485         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0486                        "child: %i %P e:%d t:%d d:%d r:%d j:%d",
0487                        i,
0488                        ngx_processes[i].pid,
0489                        ngx_processes[i].exiting,
0490                        ngx_processes[i].exited,
0491                        ngx_processes[i].detached,
0492                        ngx_processes[i].respawn,
0493                        ngx_processes[i].just_spawn);
0494 
0495         if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
0496             continue;
0497         }
0498 
0499         if (ngx_processes[i].just_spawn) {
0500             ngx_processes[i].just_spawn = 0;
0501             continue;
0502         }
0503 
0504         if (ngx_processes[i].exiting
0505             && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL))
0506         {
0507             continue;
0508         }
0509 
0510         if (ch.command) {
0511             if (ngx_write_channel(ngx_processes[i].channel[0],
0512                                   &ch, sizeof(ngx_channel_t), cycle->log)
0513                 == NGX_OK)
0514             {
0515                 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
0516                     ngx_processes[i].exiting = 1;
0517                 }
0518 
0519                 continue;
0520             }
0521         }
0522 
0523         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
0524                        "kill (%P, %d)", ngx_processes[i].pid, signo);
0525 
0526         if (kill(ngx_processes[i].pid, signo) == -1) {
0527             err = ngx_errno;
0528             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
0529                           "kill(%P, %d) failed", ngx_processes[i].pid, signo);
0530 
0531             if (err == NGX_ESRCH) {
0532                 ngx_processes[i].exited = 1;
0533                 ngx_processes[i].exiting = 0;
0534                 ngx_reap = 1;
0535             }
0536 
0537             continue;
0538         }
0539 
0540         if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
0541             ngx_processes[i].exiting = 1;
0542         }
0543     }
0544 }
0545 
0546 
0547 static ngx_uint_t
0548 ngx_reap_children(ngx_cycle_t *cycle)
0549 {
0550     ngx_int_t         i, n;
0551     ngx_uint_t        live;
0552     ngx_channel_t     ch;
0553     ngx_core_conf_t  *ccf;
0554 
0555     ngx_memzero(&ch, sizeof(ngx_channel_t));
0556 
0557     ch.command = NGX_CMD_CLOSE_CHANNEL;
0558     ch.fd = -1;
0559 
0560     live = 0;
0561     for (i = 0; i < ngx_last_process; i++) {
0562 
0563         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0564                        "child: %i %P e:%d t:%d d:%d r:%d j:%d",
0565                        i,
0566                        ngx_processes[i].pid,
0567                        ngx_processes[i].exiting,
0568                        ngx_processes[i].exited,
0569                        ngx_processes[i].detached,
0570                        ngx_processes[i].respawn,
0571                        ngx_processes[i].just_spawn);
0572 
0573         if (ngx_processes[i].pid == -1) {
0574             continue;
0575         }
0576 
0577         if (ngx_processes[i].exited) {
0578 
0579             if (!ngx_processes[i].detached) {
0580                 ngx_close_channel(ngx_processes[i].channel, cycle->log);
0581 
0582                 ngx_processes[i].channel[0] = -1;
0583                 ngx_processes[i].channel[1] = -1;
0584 
0585                 ch.pid = ngx_processes[i].pid;
0586                 ch.slot = i;
0587 
0588                 for (n = 0; n < ngx_last_process; n++) {
0589                     if (ngx_processes[n].exited
0590                         || ngx_processes[n].pid == -1
0591                         || ngx_processes[n].channel[0] == -1)
0592                     {
0593                         continue;
0594                     }
0595 
0596                     ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0,
0597                                    "pass close channel s:%i pid:%P to:%P",
0598                                    ch.slot, ch.pid, ngx_processes[n].pid);
0599 
0600                     /* TODO: NGX_AGAIN */
0601 
0602                     ngx_write_channel(ngx_processes[n].channel[0],
0603                                       &ch, sizeof(ngx_channel_t), cycle->log);
0604                 }
0605             }
0606 
0607             if (ngx_processes[i].respawn
0608                 && !ngx_processes[i].exiting
0609                 && !ngx_terminate
0610                 && !ngx_quit)
0611             {
0612                 if (ngx_spawn_process(cycle, ngx_processes[i].proc,
0613                                       ngx_processes[i].data,
0614                                       ngx_processes[i].name, i)
0615                     == NGX_INVALID_PID)
0616                 {
0617                     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0618                                   "could not respawn %s",
0619                                   ngx_processes[i].name);
0620                     continue;
0621                 }
0622 
0623 
0624                 ch.command = NGX_CMD_OPEN_CHANNEL;
0625                 ch.pid = ngx_processes[ngx_process_slot].pid;
0626                 ch.slot = ngx_process_slot;
0627                 ch.fd = ngx_processes[ngx_process_slot].channel[0];
0628 
0629                 ngx_pass_open_channel(cycle, &ch);
0630 
0631                 live = 1;
0632 
0633                 continue;
0634             }
0635 
0636             if (ngx_processes[i].pid == ngx_new_binary) {
0637 
0638                 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
0639                                                        ngx_core_module);
0640 
0641                 if (ngx_rename_file((char *) ccf->oldpid.data,
0642                                     (char *) ccf->pid.data)
0643                     == NGX_FILE_ERROR)
0644                 {
0645                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0646                                   ngx_rename_file_n " %s back to %s failed "
0647                                   "after the new binary process \"%s\" exited",
0648                                   ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
0649                 }
0650 
0651                 ngx_new_binary = 0;
0652                 if (ngx_noaccepting) {
0653                     ngx_restart = 1;
0654                     ngx_noaccepting = 0;
0655                 }
0656             }
0657 
0658             if (i == ngx_last_process - 1) {
0659                 ngx_last_process--;
0660 
0661             } else {
0662                 ngx_processes[i].pid = -1;
0663             }
0664 
0665         } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
0666             live = 1;
0667         }
0668     }
0669 
0670     return live;
0671 }
0672 
0673 
0674 static void
0675 ngx_master_process_exit(ngx_cycle_t *cycle)
0676 {
0677     ngx_uint_t  i;
0678 
0679     ngx_delete_pidfile(cycle);
0680 
0681     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
0682 
0683     for (i = 0; cycle->modules[i]; i++) {
0684         if (cycle->modules[i]->exit_master) {
0685             cycle->modules[i]->exit_master(cycle);
0686         }
0687     }
0688 
0689     ngx_close_listening_sockets(cycle);
0690 
0691     /*
0692      * Copy ngx_cycle->log related data to the special static exit cycle,
0693      * log, and log file structures enough to allow a signal handler to log.
0694      * The handler may be called when standard ngx_cycle->log allocated from
0695      * ngx_cycle->pool is already destroyed.
0696      */
0697 
0698 
0699     ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log);
0700 
0701     ngx_exit_log_file.fd = ngx_exit_log.file->fd;
0702     ngx_exit_log.file = &ngx_exit_log_file;
0703     ngx_exit_log.next = NULL;
0704     ngx_exit_log.writer = NULL;
0705 
0706     ngx_exit_cycle.log = &ngx_exit_log;
0707     ngx_exit_cycle.files = ngx_cycle->files;
0708     ngx_exit_cycle.files_n = ngx_cycle->files_n;
0709     ngx_cycle = &ngx_exit_cycle;
0710 
0711     ngx_destroy_pool(cycle->pool);
0712 
0713     exit(0);
0714 }
0715 
0716 
0717 static void
0718 ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
0719 {
0720     ngx_int_t worker = (intptr_t) data;
0721 
0722     ngx_process = NGX_PROCESS_WORKER;
0723     ngx_worker = worker;
0724 
0725     ngx_worker_process_init(cycle, worker);
0726 
0727     ngx_setproctitle("worker process");
0728 
0729     for ( ;; ) {
0730 
0731         if (ngx_exiting) {
0732             if (ngx_event_no_timers_left() == NGX_OK) {
0733                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
0734                 ngx_worker_process_exit(cycle);
0735             }
0736         }
0737 
0738         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
0739 
0740         ngx_process_events_and_timers(cycle);
0741 
0742         if (ngx_terminate) {
0743             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
0744             ngx_worker_process_exit(cycle);
0745         }
0746 
0747         if (ngx_quit) {
0748             ngx_quit = 0;
0749             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
0750                           "gracefully shutting down");
0751             ngx_setproctitle("worker process is shutting down");
0752 
0753             if (!ngx_exiting) {
0754                 ngx_exiting = 1;
0755                 ngx_set_shutdown_timer(cycle);
0756                 ngx_close_listening_sockets(cycle);
0757                 ngx_close_idle_connections(cycle);
0758             }
0759         }
0760 
0761         if (ngx_reopen) {
0762             ngx_reopen = 0;
0763             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
0764             ngx_reopen_files(cycle, -1);
0765         }
0766     }
0767 }
0768 
0769 
0770 static void
0771 ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
0772 {
0773     sigset_t          set;
0774     ngx_int_t         n;
0775     ngx_time_t       *tp;
0776     ngx_uint_t        i;
0777     ngx_cpuset_t     *cpu_affinity;
0778     struct rlimit     rlmt;
0779     ngx_core_conf_t  *ccf;
0780     ngx_listening_t  *ls;
0781 
0782     if (ngx_set_environment(cycle, NULL) == NULL) {
0783         /* fatal */
0784         exit(2);
0785     }
0786 
0787     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
0788 
0789     if (worker >= 0 && ccf->priority != 0) {
0790         if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
0791             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0792                           "setpriority(%d) failed", ccf->priority);
0793         }
0794     }
0795 
0796     if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
0797         rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
0798         rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
0799 
0800         if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
0801             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0802                           "setrlimit(RLIMIT_NOFILE, %i) failed",
0803                           ccf->rlimit_nofile);
0804         }
0805     }
0806 
0807     if (ccf->rlimit_core != NGX_CONF_UNSET) {
0808         rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
0809         rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
0810 
0811         if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
0812             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0813                           "setrlimit(RLIMIT_CORE, %O) failed",
0814                           ccf->rlimit_core);
0815         }
0816     }
0817 
0818     if (geteuid() == 0) {
0819         if (setgid(ccf->group) == -1) {
0820             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0821                           "setgid(%d) failed", ccf->group);
0822             /* fatal */
0823             exit(2);
0824         }
0825 
0826         if (initgroups(ccf->username, ccf->group) == -1) {
0827             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0828                           "initgroups(%s, %d) failed",
0829                           ccf->username, ccf->group);
0830         }
0831 
0832 #if (NGX_HAVE_PR_SET_KEEPCAPS && NGX_HAVE_CAPABILITIES)
0833         if (ccf->transparent && ccf->user) {
0834             if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
0835                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0836                               "prctl(PR_SET_KEEPCAPS, 1) failed");
0837                 /* fatal */
0838                 exit(2);
0839             }
0840         }
0841 #endif
0842 
0843         if (setuid(ccf->user) == -1) {
0844             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0845                           "setuid(%d) failed", ccf->user);
0846             /* fatal */
0847             exit(2);
0848         }
0849 
0850 #if (NGX_HAVE_CAPABILITIES)
0851         if (ccf->transparent && ccf->user) {
0852             struct __user_cap_data_struct    data;
0853             struct __user_cap_header_struct  header;
0854 
0855             ngx_memzero(&header, sizeof(struct __user_cap_header_struct));
0856             ngx_memzero(&data, sizeof(struct __user_cap_data_struct));
0857 
0858             header.version = _LINUX_CAPABILITY_VERSION_1;
0859             data.effective = CAP_TO_MASK(CAP_NET_RAW);
0860             data.permitted = data.effective;
0861 
0862             if (syscall(SYS_capset, &header, &data) == -1) {
0863                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0864                               "capset() failed");
0865                 /* fatal */
0866                 exit(2);
0867             }
0868         }
0869 #endif
0870     }
0871 
0872     if (worker >= 0) {
0873         cpu_affinity = ngx_get_cpu_affinity(worker);
0874 
0875         if (cpu_affinity) {
0876             ngx_setaffinity(cpu_affinity, cycle->log);
0877         }
0878     }
0879 
0880 #if (NGX_HAVE_PR_SET_DUMPABLE)
0881 
0882     /* allow coredump after setuid() in Linux 2.4.x */
0883 
0884     if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
0885         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0886                       "prctl(PR_SET_DUMPABLE) failed");
0887     }
0888 
0889 #endif
0890 
0891     if (ccf->working_directory.len) {
0892         if (chdir((char *) ccf->working_directory.data) == -1) {
0893             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0894                           "chdir(\"%s\") failed", ccf->working_directory.data);
0895             /* fatal */
0896             exit(2);
0897         }
0898     }
0899 
0900     sigemptyset(&set);
0901 
0902     if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
0903         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0904                       "sigprocmask() failed");
0905     }
0906 
0907     tp = ngx_timeofday();
0908     srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);
0909 
0910     /*
0911      * disable deleting previous events for the listening sockets because
0912      * in the worker processes there are no events at all at this point
0913      */
0914     ls = cycle->listening.elts;
0915     for (i = 0; i < cycle->listening.nelts; i++) {
0916         ls[i].previous = NULL;
0917     }
0918 
0919     for (i = 0; cycle->modules[i]; i++) {
0920         if (cycle->modules[i]->init_process) {
0921             if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
0922                 /* fatal */
0923                 exit(2);
0924             }
0925         }
0926     }
0927 
0928     for (n = 0; n < ngx_last_process; n++) {
0929 
0930         if (ngx_processes[n].pid == -1) {
0931             continue;
0932         }
0933 
0934         if (n == ngx_process_slot) {
0935             continue;
0936         }
0937 
0938         if (ngx_processes[n].channel[1] == -1) {
0939             continue;
0940         }
0941 
0942         if (close(ngx_processes[n].channel[1]) == -1) {
0943             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0944                           "close() channel failed");
0945         }
0946     }
0947 
0948     if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
0949         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0950                       "close() channel failed");
0951     }
0952 
0953 #if 0
0954     ngx_last_process = 0;
0955 #endif
0956 
0957     if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
0958                               ngx_channel_handler)
0959         == NGX_ERROR)
0960     {
0961         /* fatal */
0962         exit(2);
0963     }
0964 }
0965 
0966 
0967 static void
0968 ngx_worker_process_exit(ngx_cycle_t *cycle)
0969 {
0970     ngx_uint_t         i;
0971     ngx_connection_t  *c;
0972 
0973     for (i = 0; cycle->modules[i]; i++) {
0974         if (cycle->modules[i]->exit_process) {
0975             cycle->modules[i]->exit_process(cycle);
0976         }
0977     }
0978 
0979     if (ngx_exiting) {
0980         c = cycle->connections;
0981         for (i = 0; i < cycle->connection_n; i++) {
0982             if (c[i].fd != -1
0983                 && c[i].read
0984                 && !c[i].read->accept
0985                 && !c[i].read->channel
0986                 && !c[i].read->resolver)
0987             {
0988                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0989                               "*%uA open socket #%d left in connection %ui",
0990                               c[i].number, c[i].fd, i);
0991                 ngx_debug_quit = 1;
0992             }
0993         }
0994 
0995         if (ngx_debug_quit) {
0996             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
0997             ngx_debug_point();
0998         }
0999     }
1000 
1001     /*
1002      * Copy ngx_cycle->log related data to the special static exit cycle,
1003      * log, and log file structures enough to allow a signal handler to log.
1004      * The handler may be called when standard ngx_cycle->log allocated from
1005      * ngx_cycle->pool is already destroyed.
1006      */
1007 
1008     ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log);
1009 
1010     ngx_exit_log_file.fd = ngx_exit_log.file->fd;
1011     ngx_exit_log.file = &ngx_exit_log_file;
1012     ngx_exit_log.next = NULL;
1013     ngx_exit_log.writer = NULL;
1014 
1015     ngx_exit_cycle.log = &ngx_exit_log;
1016     ngx_exit_cycle.files = ngx_cycle->files;
1017     ngx_exit_cycle.files_n = ngx_cycle->files_n;
1018     ngx_cycle = &ngx_exit_cycle;
1019 
1020     ngx_destroy_pool(cycle->pool);
1021 
1022     ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit");
1023 
1024     exit(0);
1025 }
1026 
1027 
1028 static void
1029 ngx_channel_handler(ngx_event_t *ev)
1030 {
1031     ngx_int_t          n;
1032     ngx_channel_t      ch;
1033     ngx_connection_t  *c;
1034 
1035     if (ev->timedout) {
1036         ev->timedout = 0;
1037         return;
1038     }
1039 
1040     c = ev->data;
1041 
1042     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");
1043 
1044     for ( ;; ) {
1045 
1046         n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
1047 
1048         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
1049 
1050         if (n == NGX_ERROR) {
1051 
1052             if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
1053                 ngx_del_conn(c, 0);
1054             }
1055 
1056             ngx_close_connection(c);
1057             return;
1058         }
1059 
1060         if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
1061             if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
1062                 return;
1063             }
1064         }
1065 
1066         if (n == NGX_AGAIN) {
1067             return;
1068         }
1069 
1070         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
1071                        "channel command: %ui", ch.command);
1072 
1073         switch (ch.command) {
1074 
1075         case NGX_CMD_QUIT:
1076             ngx_quit = 1;
1077             break;
1078 
1079         case NGX_CMD_TERMINATE:
1080             ngx_terminate = 1;
1081             break;
1082 
1083         case NGX_CMD_REOPEN:
1084             ngx_reopen = 1;
1085             break;
1086 
1087         case NGX_CMD_OPEN_CHANNEL:
1088 
1089             ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,
1090                            "get channel s:%i pid:%P fd:%d",
1091                            ch.slot, ch.pid, ch.fd);
1092 
1093             ngx_processes[ch.slot].pid = ch.pid;
1094             ngx_processes[ch.slot].channel[0] = ch.fd;
1095             break;
1096 
1097         case NGX_CMD_CLOSE_CHANNEL:
1098 
1099             ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,
1100                            "close channel s:%i pid:%P our:%P fd:%d",
1101                            ch.slot, ch.pid, ngx_processes[ch.slot].pid,
1102                            ngx_processes[ch.slot].channel[0]);
1103 
1104             if (close(ngx_processes[ch.slot].channel[0]) == -1) {
1105                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
1106                               "close() channel failed");
1107             }
1108 
1109             ngx_processes[ch.slot].channel[0] = -1;
1110             break;
1111         }
1112     }
1113 }
1114 
1115 
1116 static void
1117 ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
1118 {
1119     ngx_cache_manager_ctx_t *ctx = data;
1120 
1121     void         *ident[4];
1122     ngx_event_t   ev;
1123 
1124     /*
1125      * Set correct process type since closing listening Unix domain socket
1126      * in a master process also removes the Unix domain socket file.
1127      */
1128     ngx_process = NGX_PROCESS_HELPER;
1129 
1130     ngx_close_listening_sockets(cycle);
1131 
1132     /* Set a moderate number of connections for a helper process. */
1133     cycle->connection_n = 512;
1134 
1135     ngx_worker_process_init(cycle, -1);
1136 
1137     ngx_memzero(&ev, sizeof(ngx_event_t));
1138     ev.handler = ctx->handler;
1139     ev.data = ident;
1140     ev.log = cycle->log;
1141     ident[3] = (void *) -1;
1142 
1143     ngx_use_accept_mutex = 0;
1144 
1145     ngx_setproctitle(ctx->name);
1146 
1147     ngx_add_timer(&ev, ctx->delay);
1148 
1149     for ( ;; ) {
1150 
1151         if (ngx_terminate || ngx_quit) {
1152             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
1153             exit(0);
1154         }
1155 
1156         if (ngx_reopen) {
1157             ngx_reopen = 0;
1158             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
1159             ngx_reopen_files(cycle, -1);
1160         }
1161 
1162         ngx_process_events_and_timers(cycle);
1163     }
1164 }
1165 
1166 
1167 static void
1168 ngx_cache_manager_process_handler(ngx_event_t *ev)
1169 {
1170     ngx_uint_t    i;
1171     ngx_msec_t    next, n;
1172     ngx_path_t  **path;
1173 
1174     next = 60 * 60 * 1000;
1175 
1176     path = ngx_cycle->paths.elts;
1177     for (i = 0; i < ngx_cycle->paths.nelts; i++) {
1178 
1179         if (path[i]->manager) {
1180             n = path[i]->manager(path[i]->data);
1181 
1182             next = (n <= next) ? n : next;
1183 
1184             ngx_time_update();
1185         }
1186     }
1187 
1188     if (next == 0) {
1189         next = 1;
1190     }
1191 
1192     ngx_add_timer(ev, next);
1193 }
1194 
1195 
1196 static void
1197 ngx_cache_loader_process_handler(ngx_event_t *ev)
1198 {
1199     ngx_uint_t     i;
1200     ngx_path_t   **path;
1201     ngx_cycle_t   *cycle;
1202 
1203     cycle = (ngx_cycle_t *) ngx_cycle;
1204 
1205     path = cycle->paths.elts;
1206     for (i = 0; i < cycle->paths.nelts; i++) {
1207 
1208         if (ngx_terminate || ngx_quit) {
1209             break;
1210         }
1211 
1212         if (path[i]->loader) {
1213             path[i]->loader(path[i]->data);
1214             ngx_time_update();
1215         }
1216     }
1217 
1218     exit(0);
1219 }