src/os/unix/ngx_process_cycle.c - nginx-1.31.9 nginx/ @ 2a3a19c6f

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>
  8. #include <ngx_channel.h>


  9. static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
  10.     ngx_int_t type);
  11. static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle,
  12.     ngx_uint_t respawn);
  13. static void ngx_pass_open_channel(ngx_cycle_t *cycle);
  14. static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
  15. static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
  16. static void ngx_master_process_exit(ngx_cycle_t *cycle);
  17. static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
  18. static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker);
  19. static void ngx_worker_process_exit(ngx_cycle_t *cycle);
  20. static void ngx_channel_handler(ngx_event_t *ev);
  21. static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data);
  22. static void ngx_cache_manager_process_handler(ngx_event_t *ev);
  23. static void ngx_cache_loader_process_handler(ngx_event_t *ev);


  24. ‌ngx_uint_t    ngx_process;
  25. ‌ngx_uint_t    ngx_worker;
  26. ‌ngx_pid_t     ngx_pid;
  27. ‌ngx_pid_t     ngx_parent;

  28. ‌sig_atomic_t  ngx_reap;
  29. ‌sig_atomic_t  ngx_sigio;
  30. ‌sig_atomic_t  ngx_sigalrm;
  31. ‌sig_atomic_t  ngx_terminate;
  32. ‌sig_atomic_t  ngx_quit;
  33. ‌sig_atomic_t  ngx_debug_quit;
  34. ‌ngx_uint_t    ngx_exiting;
  35. ‌sig_atomic_t  ngx_reconfigure;
  36. ‌sig_atomic_t  ngx_reopen;

  37. ‌sig_atomic_t  ngx_change_binary;
  38. ‌ngx_pid_t     ngx_new_binary;
  39. ‌ngx_uint_t    ngx_inherited;
  40. ‌ngx_uint_t    ngx_daemonized;

  41. ‌sig_atomic_t  ngx_noaccept;
  42. ‌ngx_uint_t    ngx_noaccepting;
  43. ‌ngx_uint_t    ngx_restart;


  44. ‌static u_char  master_process[] = "master process";


  45. ‌static ngx_cache_manager_ctx_t  ngx_cache_manager_ctx = {
  46.     ngx_cache_manager_process_handler, "cache manager process", 0
  47. };

  48. ‌static ngx_cache_manager_ctx_t  ngx_cache_loader_ctx = {
  49.     ngx_cache_loader_process_handler, "cache loader process", 60000
  50. };


  51. ‌static ngx_cycle_t      ngx_exit_cycle;
  52. ‌static ngx_log_t        ngx_exit_log;
  53. ‌static ngx_open_file_t  ngx_exit_log_file;


  54. void
  55. ‌ngx_master_process_cycle(ngx_cycle_t *cycle)
  56. {
  57.     char              *title;
  58.     u_char            *p;
  59.     size_t             size;
  60.     ngx_int_t          i;
  61.     ngx_uint_t         sigio;
  62.     sigset_t           set;
  63.     struct itimerval   itv;
  64.     ngx_uint_t         live;
  65.     ngx_msec_t         delay;
  66.     ngx_core_conf_t   *ccf;

  67.     sigemptyset(&set);
  68.     sigaddset(&set, SIGCHLD);
  69.     sigaddset(&set, SIGALRM);
  70.     sigaddset(&set, SIGIO);
  71.     sigaddset(&set, SIGINT);
  72.     sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
  73.     sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
  74.     sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
  75.     sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
  76.     sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  77.     sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));

  78.     if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
  79.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  80.                       "sigprocmask() failed");
  81.     }

  82.     sigemptyset(&set);


  83.     size = sizeof(master_process);

  84.     for (i = 0; i < ngx_argc; i++) {
  85.         size += ngx_strlen(ngx_argv[i]) + 1;
  86.     }

  87.     title = ngx_pnalloc(cycle->pool, size);
  88.     if (title == NULL) {
  89.         /* fatal */
  90.         exit(2);
  91.     }

  92.     p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);
  93.     for (i = 0; i < ngx_argc; i++) {
  94.         *p++ = ' ';
  95.         p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
  96.     }

  97.     ngx_setproctitle(title);


  98.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  99.     ngx_start_worker_processes(cycle, ccf->worker_processes,
  100.                                NGX_PROCESS_RESPAWN);
  101.     ngx_start_cache_manager_processes(cycle, 0);

  102.     ngx_new_binary = 0;
  103.     delay = 0;
  104.     sigio = 0;
  105.     live = 1;

  106.     for ( ;; ) {
  107.         if (delay) {
  108.             if (ngx_sigalrm) {
  109.                 sigio = 0;
  110.                 delay *= 2;
  111.                 ngx_sigalrm = 0;
  112.             }

  113.             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  114.                            "termination cycle: %M", delay);

  115.             itv.it_interval.tv_sec = 0;
  116.             itv.it_interval.tv_usec = 0;
  117.             itv.it_value.tv_sec = delay / 1000;
  118.             itv.it_value.tv_usec = (delay % 1000 ) * 1000;

  119.             if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
  120.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  121.                               "setitimer() failed");
  122.             }
  123.         }

  124.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");

  125.         sigsuspend(&set);

  126.         ngx_time_update();

  127.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  128.                        "wake up, sigio %i", sigio);

  129.         if (ngx_reap) {
  130.             ngx_reap = 0;
  131.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");

  132.             live = ngx_reap_children(cycle);
  133.         }

  134. #if (NGX_CONTROL_API)
  135.         if (ngx_sigio) {
  136.             ngx_sigio = 0;

  137.             if (ngx_control_handle_events() == NGX_DONE) {
  138.                 cycle = (ngx_cycle_t *) ngx_cycle;
  139.                 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
  140.                                                        ngx_core_module);
  141.                 ngx_start_worker_processes(cycle, ccf->worker_processes,
  142.                                            NGX_PROCESS_JUST_RESPAWN);
  143.                 ngx_start_cache_manager_processes(cycle, 1);

  144.                 /* allow new processes to start */
  145.                 ngx_msleep(100);

  146.                 live = 1;
  147.                 ngx_signal_worker_processes(cycle,
  148.                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  149.             }
  150.         }
  151. #endif

  152.         if (!live && (ngx_terminate || ngx_quit)) {
  153.             ngx_master_process_exit(cycle);
  154.         }

  155.         if (ngx_terminate) {
  156.             if (delay == 0) {
  157.                 delay = 50;
  158.             }

  159.             if (sigio) {
  160.                 sigio--;
  161.                 continue;
  162.             }

  163.             sigio = ccf->worker_processes + 2 /* cache processes */;

  164.             if (delay > 1000) {
  165.                 ngx_signal_worker_processes(cycle, SIGKILL);
  166.             } else {
  167.                 ngx_signal_worker_processes(cycle,
  168.                                        ngx_signal_value(NGX_TERMINATE_SIGNAL));
  169.             }

  170.             continue;
  171.         }

  172.         if (ngx_quit) {
  173.             ngx_signal_worker_processes(cycle,
  174.                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  175.             ngx_close_listening_sockets(cycle);

  176.             continue;
  177.         }

  178.         if (ngx_reconfigure) {
  179.             ngx_reconfigure = 0;

  180.             if (ngx_new_binary) {
  181.                 ngx_start_worker_processes(cycle, ccf->worker_processes,
  182.                                            NGX_PROCESS_RESPAWN);
  183.                 ngx_start_cache_manager_processes(cycle, 0);
  184.                 ngx_noaccepting = 0;

  185.                 continue;
  186.             }

  187.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");

  188.             cycle = ngx_init_cycle(cycle);
  189.             if (cycle == NULL) {
  190.                 cycle = (ngx_cycle_t *) ngx_cycle;
  191.                 continue;
  192.             }

  193.             ngx_cycle = cycle;
  194.             ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
  195.                                                    ngx_core_module);
  196.             ngx_start_worker_processes(cycle, ccf->worker_processes,
  197.                                        NGX_PROCESS_JUST_RESPAWN);
  198.             ngx_start_cache_manager_processes(cycle, 1);

  199.             /* allow new processes to start */
  200.             ngx_msleep(100);

  201.             live = 1;
  202.             ngx_signal_worker_processes(cycle,
  203.                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  204.         }

  205.         if (ngx_restart) {
  206.             ngx_restart = 0;
  207.             ngx_start_worker_processes(cycle, ccf->worker_processes,
  208.                                        NGX_PROCESS_RESPAWN);
  209.             ngx_start_cache_manager_processes(cycle, 0);
  210.             live = 1;
  211.         }

  212.         if (ngx_reopen) {
  213.             ngx_reopen = 0;
  214.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  215.             ngx_reopen_files(cycle, ccf->user);
  216.             ngx_signal_worker_processes(cycle,
  217.                                         ngx_signal_value(NGX_REOPEN_SIGNAL));
  218.         }

  219.         if (ngx_change_binary) {
  220.             ngx_change_binary = 0;
  221.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
  222.             ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv);
  223.         }

  224.         if (ngx_noaccept) {
  225.             ngx_noaccept = 0;
  226.             ngx_noaccepting = 1;
  227.             ngx_signal_worker_processes(cycle,
  228.                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  229.         }
  230.     }
  231. }


  232. void
  233. ‌ngx_single_process_cycle(ngx_cycle_t *cycle)
  234. {
  235.     ngx_uint_t  i;

  236.     if (ngx_set_environment(cycle, NULL) == NULL) {
  237.         /* fatal */
  238.         exit(2);
  239.     }

  240.     for (i = 0; cycle->modules[i]; i++) {
  241.         if (cycle->modules[i]->init_process) {
  242.             if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
  243.                 /* fatal */
  244.                 exit(2);
  245.             }
  246.         }
  247.     }

  248.     for ( ;; ) {
  249.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");

  250.         ngx_process_events_and_timers(cycle);

  251.         if (ngx_terminate || ngx_quit) {

  252.             for (i = 0; cycle->modules[i]; i++) {
  253.                 if (cycle->modules[i]->exit_process) {
  254.                     cycle->modules[i]->exit_process(cycle);
  255.                 }
  256.             }

  257.             ngx_master_process_exit(cycle);
  258.         }

  259.         if (ngx_reconfigure) {
  260.             ngx_reconfigure = 0;
  261.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");

  262.             cycle = ngx_init_cycle(cycle);
  263.             if (cycle == NULL) {
  264.                 cycle = (ngx_cycle_t *) ngx_cycle;
  265.                 continue;
  266.             }

  267.             ngx_cycle = cycle;
  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, (ngx_uid_t) -1);
  273.         }
  274.     }
  275. }


  276. static void
  277. ‌ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
  278. {
  279.     ngx_int_t  i;

  280.     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");

  281.     for (i = 0; i < n; i++) {

  282.         ngx_spawn_process(cycle, ngx_worker_process_cycle,
  283.                           (void *) (intptr_t) i, "worker process", type);

  284.         ngx_pass_open_channel(cycle);
  285.     }
  286. }


  287. static void
  288. ‌ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
  289. {
  290.     ngx_uint_t    i, manager, loader;
  291.     ngx_path_t  **path;

  292.     manager = 0;
  293.     loader = 0;

  294.     path = ngx_cycle->paths.elts;
  295.     for (i = 0; i < ngx_cycle->paths.nelts; i++) {

  296.         if (path[i]->manager) {
  297.             manager = 1;
  298.         }

  299.         if (path[i]->loader) {
  300.             loader = 1;
  301.         }
  302.     }

  303.     if (manager == 0) {
  304.         return;
  305.     }

  306.     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
  307.                       &ngx_cache_manager_ctx, "cache manager process",
  308.                       respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);

  309.     ngx_pass_open_channel(cycle);

  310.     if (loader == 0) {
  311.         return;
  312.     }

  313.     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
  314.                       &ngx_cache_loader_ctx, "cache loader process",
  315.                       respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);

  316.     ngx_pass_open_channel(cycle);
  317. }


  318. static void
  319. ‌ngx_pass_open_channel(ngx_cycle_t *cycle)
  320. {
  321.     ngx_int_t      i;
  322.     ngx_channel_t  ch;

  323.     ngx_memzero(&ch, sizeof(ngx_channel_t));

  324.     ch.command = NGX_CMD_OPEN_CHANNEL;
  325.     ch.pid = ngx_processes[ngx_process_slot].pid;
  326.     ch.slot = ngx_process_slot;
  327.     ch.fd = ngx_processes[ngx_process_slot].channel[0];

  328.     for (i = 0; i < ngx_last_process; i++) {

  329.         if (i == ngx_process_slot
  330.             || ngx_processes[i].pid == -1
  331.             || ngx_processes[i].channel[0] == -1)
  332.         {
  333.             continue;
  334.         }

  335.         ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  336.                       "pass channel s:%i pid:%P fd:%d to s:%i pid:%P fd:%d",
  337.                       ch.slot, ch.pid, ch.fd,
  338.                       i, ngx_processes[i].pid,
  339.                       ngx_processes[i].channel[0]);

  340.         /* TODO: NGX_AGAIN */

  341.         ngx_write_channel(ngx_processes[i].channel[0],
  342.                           &ch, sizeof(ngx_channel_t), cycle->log);
  343.     }
  344. }


  345. static void
  346. ‌ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
  347. {
  348.     ngx_int_t      i;
  349.     ngx_err_t      err;
  350.     ngx_channel_t  ch;

  351.     ngx_memzero(&ch, sizeof(ngx_channel_t));

  352. #if (NGX_BROKEN_SCM_RIGHTS)

  353.     ch.command = 0;

  354. #else

  355.     switch (signo) {

  356.     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
  357.         ch.command = NGX_CMD_QUIT;
  358.         break;

  359.     case ngx_signal_value(NGX_TERMINATE_SIGNAL):
  360.         ch.command = NGX_CMD_TERMINATE;
  361.         break;

  362.     case ngx_signal_value(NGX_REOPEN_SIGNAL):
  363.         ch.command = NGX_CMD_REOPEN;
  364.         break;

  365.     default:
  366.         ch.command = 0;
  367.     }

  368. #endif

  369.     ch.fd = -1;


  370.     for (i = 0; i < ngx_last_process; i++) {

  371.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  372.                        "child: %i %P e:%d t:%d d:%d r:%d j:%d",
  373.                        i,
  374.                        ngx_processes[i].pid,
  375.                        ngx_processes[i].exiting,
  376.                        ngx_processes[i].exited,
  377.                        ngx_processes[i].detached,
  378.                        ngx_processes[i].respawn,
  379.                        ngx_processes[i].just_spawn);

  380.         if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
  381.             continue;
  382.         }

  383.         if (ngx_processes[i].just_spawn) {
  384.             ngx_processes[i].just_spawn = 0;
  385.             continue;
  386.         }

  387.         if (ngx_processes[i].exiting
  388.             && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL))
  389.         {
  390.             continue;
  391.         }

  392.         if (ch.command) {
  393.             if (ngx_write_channel(ngx_processes[i].channel[0],
  394.                                   &ch, sizeof(ngx_channel_t), cycle->log)
  395.                 == NGX_OK)
  396.             {
  397.                 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
  398.                     ngx_processes[i].exiting = 1;
  399.                 }

  400.                 continue;
  401.             }
  402.         }

  403.         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  404.                        "kill (%P, %d)", ngx_processes[i].pid, signo);

  405.         if (kill(ngx_processes[i].pid, signo) == -1) {
  406.             err = ngx_errno;
  407.             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
  408.                           "kill(%P, %d) failed", ngx_processes[i].pid, signo);

  409.             if (err == NGX_ESRCH) {
  410.                 ngx_processes[i].exited = 1;
  411.                 ngx_processes[i].exiting = 0;
  412.                 ngx_reap = 1;
  413.             }

  414.             continue;
  415.         }

  416.         if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
  417.             ngx_processes[i].exiting = 1;
  418.         }
  419.     }
  420. }


  421. static ngx_uint_t
  422. ‌ngx_reap_children(ngx_cycle_t *cycle)
  423. {
  424.     ngx_int_t         i, n;
  425.     ngx_uint_t        live;
  426.     ngx_channel_t     ch;
  427.     ngx_core_conf_t  *ccf;

  428.     ngx_memzero(&ch, sizeof(ngx_channel_t));

  429.     ch.command = NGX_CMD_CLOSE_CHANNEL;
  430.     ch.fd = -1;

  431.     live = 0;
  432.     for (i = 0; i < ngx_last_process; i++) {

  433.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  434.                        "child: %i %P e:%d t:%d d:%d r:%d j:%d",
  435.                        i,
  436.                        ngx_processes[i].pid,
  437.                        ngx_processes[i].exiting,
  438.                        ngx_processes[i].exited,
  439.                        ngx_processes[i].detached,
  440.                        ngx_processes[i].respawn,
  441.                        ngx_processes[i].just_spawn);

  442.         if (ngx_processes[i].pid == -1) {
  443.             continue;
  444.         }

  445.         if (ngx_processes[i].exited) {

  446.             if (!ngx_processes[i].detached) {
  447.                 ngx_close_channel(ngx_processes[i].channel, cycle->log);

  448.                 ngx_processes[i].channel[0] = -1;
  449.                 ngx_processes[i].channel[1] = -1;

  450.                 ch.pid = ngx_processes[i].pid;
  451.                 ch.slot = i;

  452.                 for (n = 0; n < ngx_last_process; n++) {
  453.                     if (ngx_processes[n].exited
  454.                         || ngx_processes[n].pid == -1
  455.                         || ngx_processes[n].channel[0] == -1)
  456.                     {
  457.                         continue;
  458.                     }

  459.                     ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  460.                                    "pass close channel s:%i pid:%P to:%P",
  461.                                    ch.slot, ch.pid, ngx_processes[n].pid);

  462.                     /* TODO: NGX_AGAIN */

  463.                     ngx_write_channel(ngx_processes[n].channel[0],
  464.                                       &ch, sizeof(ngx_channel_t), cycle->log);
  465.                 }
  466.             }

  467.             if (ngx_processes[i].respawn
  468.                 && !ngx_processes[i].exiting
  469.                 && !ngx_terminate
  470.                 && !ngx_quit)
  471.             {
  472.                 if (ngx_spawn_process(cycle, ngx_processes[i].proc,
  473.                                       ngx_processes[i].data,
  474.                                       ngx_processes[i].name, i)
  475.                     == NGX_INVALID_PID)
  476.                 {
  477.                     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  478.                                   "could not respawn %s",
  479.                                   ngx_processes[i].name);
  480.                     continue;
  481.                 }


  482.                 ngx_pass_open_channel(cycle);

  483.                 live = 1;

  484.                 continue;
  485.             }

  486.             if (ngx_processes[i].pid == ngx_new_binary) {

  487.                 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
  488.                                                        ngx_core_module);

  489.                 if (ngx_rename_file((char *) ccf->oldpid.data,
  490.                                     (char *) ccf->pid.data)
  491.                     == NGX_FILE_ERROR)
  492.                 {
  493.                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  494.                                   ngx_rename_file_n " %s back to %s failed "
  495.                                   "after the new binary process \"%s\" exited",
  496.                                   ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
  497.                 }

  498. #if (NGX_CONTROL_API)
  499.                 ngx_control_reown();
  500. #endif

  501.                 ngx_new_binary = 0;
  502.                 if (ngx_noaccepting) {
  503.                     ngx_restart = 1;
  504.                     ngx_noaccepting = 0;
  505.                 }
  506.             }

  507.             if (i == ngx_last_process - 1) {
  508.                 ngx_last_process--;

  509.             } else {
  510.                 ngx_processes[i].pid = -1;
  511.             }

  512.         } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
  513.             live = 1;
  514.         }
  515.     }

  516.     return live;
  517. }


  518. static void
  519. ‌ngx_master_process_exit(ngx_cycle_t *cycle)
  520. {
  521.     ngx_uint_t  i;

  522.     ngx_delete_pidfile(cycle);

  523.     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");

  524.     for (i = 0; cycle->modules[i]; i++) {
  525.         if (cycle->modules[i]->exit_master) {
  526.             cycle->modules[i]->exit_master(cycle);
  527.         }
  528.     }

  529.     ngx_close_listening_sockets(cycle);

  530. #if (NGX_CONTROL_API)
  531.     ngx_control_uninit();
  532. #endif

  533.     /*
  534.      * Copy ngx_cycle->log related data to the special static exit cycle,
  535.      * log, and log file structures enough to allow a signal handler to log.
  536.      * The handler may be called when standard ngx_cycle->log allocated from
  537.      * ngx_cycle->pool is already destroyed.
  538.      */


  539.     ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log);

  540.     ngx_exit_log_file.fd = ngx_exit_log.file->fd;
  541.     ngx_exit_log.file = &ngx_exit_log_file;
  542.     ngx_exit_log.next = NULL;
  543.     ngx_exit_log.writer = NULL;

  544.     ngx_exit_cycle.log = &ngx_exit_log;
  545.     ngx_exit_cycle.files = ngx_cycle->files;
  546.     ngx_exit_cycle.files_n = ngx_cycle->files_n;
  547.     ngx_cycle = &ngx_exit_cycle;

  548.     ngx_destroy_pool(cycle->pool);

  549.     exit(0);
  550. }


  551. static void
  552. ‌ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
  553. {
  554.     ngx_int_t worker = (intptr_t) data;

  555.     ngx_process = NGX_PROCESS_WORKER;
  556.     ngx_worker = worker;

  557.     ngx_worker_process_init(cycle, worker);

  558.     ngx_setproctitle("worker process");

  559.     for ( ;; ) {

  560.         if (ngx_exiting) {
  561.             if (ngx_event_no_timers_left() == NGX_OK) {
  562.                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  563.                 ngx_worker_process_exit(cycle);
  564.             }
  565.         }

  566.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");

  567.         ngx_process_events_and_timers(cycle);

  568.         if (ngx_terminate) {
  569.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  570.             ngx_worker_process_exit(cycle);
  571.         }

  572.         if (ngx_quit) {
  573.             ngx_quit = 0;
  574.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
  575.                           "gracefully shutting down");
  576.             ngx_setproctitle("worker process is shutting down");

  577.             if (!ngx_exiting) {
  578.                 ngx_exiting = 1;
  579.                 ngx_set_shutdown_timer(cycle);
  580.                 ngx_close_listening_sockets(cycle);
  581.                 ngx_close_idle_connections(cycle);
  582.                 ngx_event_process_posted(cycle, &ngx_posted_events);
  583.             }
  584.         }

  585.         if (ngx_reopen) {
  586.             ngx_reopen = 0;
  587.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  588.             ngx_reopen_files(cycle, -1);
  589.         }
  590.     }
  591. }


  592. static void
  593. ‌ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
  594. {
  595.     sigset_t          set;
  596.     ngx_int_t         n;
  597.     ngx_time_t       *tp;
  598.     ngx_uint_t        i;
  599.     ngx_cpuset_t     *cpu_affinity;
  600.     struct rlimit     rlmt;
  601.     ngx_core_conf_t  *ccf;

  602. #if (NGX_CONTROL_API)
  603.     ngx_control_close_sockets();
  604. #endif

  605.     if (ngx_set_environment(cycle, NULL) == NULL) {
  606.         /* fatal */
  607.         exit(2);
  608.     }

  609.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  610.     if (worker >= 0 && ccf->priority != 0) {
  611.         if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
  612.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  613.                           "setpriority(%d) failed", ccf->priority);
  614.         }
  615.     }

  616.     if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
  617.         rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
  618.         rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;

  619.         if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
  620.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  621.                           "setrlimit(RLIMIT_NOFILE, %i) failed",
  622.                           ccf->rlimit_nofile);
  623.         }
  624.     }

  625.     if (ccf->rlimit_core != NGX_CONF_UNSET) {
  626.         rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
  627.         rlmt.rlim_max = (rlim_t) ccf->rlimit_core;

  628.         if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
  629.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  630.                           "setrlimit(RLIMIT_CORE, %O) failed",
  631.                           ccf->rlimit_core);
  632.         }
  633.     }

  634.     if (geteuid() == 0) {
  635.         if (setgid(ccf->group) == -1) {
  636.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  637.                           "setgid(%d) failed", ccf->group);
  638.             /* fatal */
  639.             exit(2);
  640.         }

  641.         if (initgroups(ccf->username, ccf->group) == -1) {

  642.             if (ngx_errno != NGX_EPERM) {
  643.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  644.                               "initgroups(%s, %d) failed",
  645.                               ccf->username, ccf->group);
  646.                 /* fatal */
  647.                 exit(2);
  648.             }

  649.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  650.                           "initgroups(%s, %d) failed, ignored",
  651.                           ccf->username, ccf->group);
  652.         }

  653. #if (NGX_HAVE_PR_SET_KEEPCAPS && NGX_HAVE_CAPABILITIES)
  654.         if (ccf->transparent && ccf->user) {
  655.             if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
  656.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  657.                               "prctl(PR_SET_KEEPCAPS, 1) failed");
  658.                 /* fatal */
  659.                 exit(2);
  660.             }
  661.         }
  662. #endif

  663.         if (setuid(ccf->user) == -1) {
  664.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  665.                           "setuid(%d) failed", ccf->user);
  666.             /* fatal */
  667.             exit(2);
  668.         }

  669. #if (NGX_HAVE_CAPABILITIES)
  670.         if (ccf->transparent && ccf->user) {
  671.             struct __user_cap_data_struct    data;
  672.             struct __user_cap_header_struct  header;

  673.             ngx_memzero(&header, sizeof(struct __user_cap_header_struct));
  674.             ngx_memzero(&data, sizeof(struct __user_cap_data_struct));

  675.             header.version = _LINUX_CAPABILITY_VERSION_1;
  676.             data.effective = CAP_TO_MASK(CAP_NET_RAW);
  677.             data.permitted = data.effective;

  678.             if (syscall(SYS_capset, &header, &data) == -1) {
  679.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  680.                               "capset() failed");
  681.                 /* fatal */
  682.                 exit(2);
  683.             }
  684.         }
  685. #endif
  686.     }

  687.     if (worker >= 0) {
  688.         cpu_affinity = ngx_get_cpu_affinity(worker);

  689.         if (cpu_affinity) {
  690.             ngx_setaffinity(cpu_affinity, cycle->log);
  691.         }
  692.     }

  693. #if (NGX_HAVE_PR_SET_DUMPABLE)

  694.     /* allow coredump after setuid() in Linux 2.4.x */

  695.     if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
  696.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  697.                       "prctl(PR_SET_DUMPABLE) failed");
  698.     }

  699. #endif

  700.     if (ccf->working_directory.len) {
  701.         if (chdir((char *) ccf->working_directory.data) == -1) {
  702.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  703.                           "chdir(\"%s\") failed", ccf->working_directory.data);
  704.             /* fatal */
  705.             exit(2);
  706.         }
  707.     }

  708.     sigemptyset(&set);

  709.     if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
  710.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  711.                       "sigprocmask() failed");
  712.     }

  713.     tp = ngx_timeofday();
  714.     srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);

  715.     for (i = 0; cycle->modules[i]; i++) {
  716.         if (cycle->modules[i]->init_process) {
  717.             if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
  718.                 /* fatal */
  719.                 exit(2);
  720.             }
  721.         }
  722.     }

  723.     for (n = 0; n < ngx_last_process; n++) {

  724.         if (ngx_processes[n].pid == -1) {
  725.             continue;
  726.         }

  727.         if (n == ngx_process_slot) {
  728.             continue;
  729.         }

  730.         if (ngx_processes[n].channel[1] == -1) {
  731.             continue;
  732.         }

  733.         if (close(ngx_processes[n].channel[1]) == -1) {
  734.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  735.                           "close() channel failed");
  736.         }
  737.     }

  738.     if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
  739.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  740.                       "close() channel failed");
  741.     }

  742. #if 0
  743.     ngx_last_process = 0;
  744. #endif

  745.     if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
  746.                               ngx_channel_handler)
  747.         == NGX_ERROR)
  748.     {
  749.         /* fatal */
  750.         exit(2);
  751.     }
  752. }


  753. static void
  754. ‌ngx_worker_process_exit(ngx_cycle_t *cycle)
  755. {
  756.     ngx_uint_t         i;
  757.     ngx_connection_t  *c;

  758.     for (i = 0; cycle->modules[i]; i++) {
  759.         if (cycle->modules[i]->exit_process) {
  760.             cycle->modules[i]->exit_process(cycle);
  761.         }
  762.     }

  763.     if (ngx_exiting && !ngx_terminate) {
  764.         c = cycle->connections;
  765.         for (i = 0; i < cycle->connection_n; i++) {
  766.             if (c[i].fd != -1
  767.                 && c[i].read
  768.                 && !c[i].read->accept
  769.                 && !c[i].read->channel
  770.                 && !c[i].read->resolver
  771.                 && !c[i].read->quic)
  772.             {
  773.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  774.                               "*%uA open socket #%d left in connection %ui",
  775.                               c[i].number, c[i].fd, i);
  776.                 ngx_debug_quit = 1;
  777.             }
  778.         }
  779.     }

  780.     if (ngx_debug_quit) {
  781.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
  782.         ngx_debug_point();
  783.     }

  784.     /*
  785.      * Copy ngx_cycle->log related data to the special static exit cycle,
  786.      * log, and log file structures enough to allow a signal handler to log.
  787.      * The handler may be called when standard ngx_cycle->log allocated from
  788.      * ngx_cycle->pool is already destroyed.
  789.      */

  790.     ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log);

  791.     ngx_exit_log_file.fd = ngx_exit_log.file->fd;
  792.     ngx_exit_log.file = &ngx_exit_log_file;
  793.     ngx_exit_log.next = NULL;
  794.     ngx_exit_log.writer = NULL;

  795.     ngx_exit_cycle.log = &ngx_exit_log;
  796.     ngx_exit_cycle.files = ngx_cycle->files;
  797.     ngx_exit_cycle.files_n = ngx_cycle->files_n;
  798.     ngx_cycle = &ngx_exit_cycle;

  799.     ngx_destroy_pool(cycle->pool);

  800.     ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit");

  801.     exit(0);
  802. }


  803. static void
  804. ‌ngx_channel_handler(ngx_event_t *ev)
  805. {
  806.     ngx_int_t          n;
  807.     ngx_channel_t      ch;
  808.     ngx_connection_t  *c;

  809.     if (ev->timedout) {
  810.         ev->timedout = 0;
  811.         return;
  812.     }

  813.     c = ev->data;

  814.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");

  815.     for ( ;; ) {

  816.         n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);

  817.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);

  818.         if (n == NGX_ERROR) {

  819.             if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
  820.                 ngx_del_conn(c, 0);
  821.             }

  822.             ngx_close_connection(c);
  823.             return;
  824.         }

  825.         if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
  826.             if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  827.                 return;
  828.             }
  829.         }

  830.         if (n == NGX_AGAIN) {
  831.             return;
  832.         }

  833.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
  834.                        "channel command: %ui", ch.command);

  835.         switch (ch.command) {

  836.         case NGX_CMD_QUIT:
  837.             ngx_quit = 1;
  838.             break;

  839.         case NGX_CMD_TERMINATE:
  840.             ngx_terminate = 1;
  841.             break;

  842.         case NGX_CMD_REOPEN:
  843.             ngx_reopen = 1;
  844.             break;

  845.         case NGX_CMD_OPEN_CHANNEL:

  846.             ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,
  847.                            "get channel s:%i pid:%P fd:%d",
  848.                            ch.slot, ch.pid, ch.fd);

  849.             ngx_processes[ch.slot].pid = ch.pid;
  850.             ngx_processes[ch.slot].channel[0] = ch.fd;
  851.             break;

  852.         case NGX_CMD_CLOSE_CHANNEL:

  853.             ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,
  854.                            "close channel s:%i pid:%P our:%P fd:%d",
  855.                            ch.slot, ch.pid, ngx_processes[ch.slot].pid,
  856.                            ngx_processes[ch.slot].channel[0]);

  857.             if (ngx_processes[ch.slot].channel[0] == -1
  858.                 || ngx_processes[ch.slot].pid != ch.pid)
  859.             {
  860.                 break;
  861.             }

  862.             if (close(ngx_processes[ch.slot].channel[0]) == -1) {
  863.                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  864.                               "close() channel failed");
  865.             }

  866.             ngx_processes[ch.slot].channel[0] = -1;
  867.             break;
  868.         }
  869.     }
  870. }


  871. static void
  872. ‌ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
  873. {
  874.     ngx_cache_manager_ctx_t *ctx = data;

  875.     void         *ident[4];
  876.     ngx_event_t   ev;

  877.     /*
  878.      * Set correct process type since closing listening Unix domain socket
  879.      * in a master process also removes the Unix domain socket file.
  880.      */
  881.     ngx_process = NGX_PROCESS_HELPER;

  882.     ngx_close_listening_sockets(cycle);

  883.     /* Set a moderate number of connections for a helper process. */
  884.     cycle->connection_n = 512;

  885.     ngx_worker_process_init(cycle, -1);

  886.     ngx_memzero(&ev, sizeof(ngx_event_t));
  887.     ev.handler = ctx->handler;
  888.     ev.data = ident;
  889.     ev.log = cycle->log;
  890.     ident[3] = (void *) -1;

  891.     ngx_use_accept_mutex = 0;

  892.     ngx_setproctitle(ctx->name);

  893.     ngx_add_timer(&ev, ctx->delay);

  894.     for ( ;; ) {

  895.         if (ngx_terminate || ngx_quit) {
  896.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  897.             exit(0);
  898.         }

  899.         if (ngx_reopen) {
  900.             ngx_reopen = 0;
  901.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  902.             ngx_reopen_files(cycle, -1);
  903.         }

  904.         ngx_process_events_and_timers(cycle);
  905.     }
  906. }


  907. static void
  908. ‌ngx_cache_manager_process_handler(ngx_event_t *ev)
  909. {
  910.     ngx_uint_t    i;
  911.     ngx_msec_t    next, n;
  912.     ngx_path_t  **path;

  913.     next = 60 * 60 * 1000;

  914.     path = ngx_cycle->paths.elts;
  915.     for (i = 0; i < ngx_cycle->paths.nelts; i++) {

  916.         if (path[i]->manager) {
  917.             n = path[i]->manager(path[i]->data);

  918.             next = (n <= next) ? n : next;

  919.             ngx_time_update();
  920.         }
  921.     }

  922.     if (next == 0) {
  923.         next = 1;
  924.     }

  925.     ngx_add_timer(ev, next);
  926. }


  927. static void
  928. ‌ngx_cache_loader_process_handler(ngx_event_t *ev)
  929. {
  930.     ngx_uint_t     i;
  931.     ngx_path_t   **path;
  932.     ngx_cycle_t   *cycle;

  933.     cycle = (ngx_cycle_t *) ngx_cycle;

  934.     path = cycle->paths.elts;
  935.     for (i = 0; i < cycle->paths.nelts; i++) {

  936.         if (ngx_terminate || ngx_quit) {
  937.             break;
  938.         }

  939.         if (path[i]->loader) {
  940.             path[i]->loader(path[i]->data);
  941.             ngx_time_update();
  942.         }
  943.     }

  944.     exit(0);
  945. }