src/os/unix/ngx_process_cycle.c - nginx-1.31.7 nginx/ @ 939334eff

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.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  643.                           "initgroups(%s, %d) failed",
  644.                           ccf->username, ccf->group);
  645.         }

  646. #if (NGX_HAVE_PR_SET_KEEPCAPS && NGX_HAVE_CAPABILITIES)
  647.         if (ccf->transparent && ccf->user) {
  648.             if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
  649.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  650.                               "prctl(PR_SET_KEEPCAPS, 1) failed");
  651.                 /* fatal */
  652.                 exit(2);
  653.             }
  654.         }
  655. #endif

  656.         if (setuid(ccf->user) == -1) {
  657.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  658.                           "setuid(%d) failed", ccf->user);
  659.             /* fatal */
  660.             exit(2);
  661.         }

  662. #if (NGX_HAVE_CAPABILITIES)
  663.         if (ccf->transparent && ccf->user) {
  664.             struct __user_cap_data_struct    data;
  665.             struct __user_cap_header_struct  header;

  666.             ngx_memzero(&header, sizeof(struct __user_cap_header_struct));
  667.             ngx_memzero(&data, sizeof(struct __user_cap_data_struct));

  668.             header.version = _LINUX_CAPABILITY_VERSION_1;
  669.             data.effective = CAP_TO_MASK(CAP_NET_RAW);
  670.             data.permitted = data.effective;

  671.             if (syscall(SYS_capset, &header, &data) == -1) {
  672.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  673.                               "capset() failed");
  674.                 /* fatal */
  675.                 exit(2);
  676.             }
  677.         }
  678. #endif
  679.     }

  680.     if (worker >= 0) {
  681.         cpu_affinity = ngx_get_cpu_affinity(worker);

  682.         if (cpu_affinity) {
  683.             ngx_setaffinity(cpu_affinity, cycle->log);
  684.         }
  685.     }

  686. #if (NGX_HAVE_PR_SET_DUMPABLE)

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

  688.     if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
  689.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  690.                       "prctl(PR_SET_DUMPABLE) failed");
  691.     }

  692. #endif

  693.     if (ccf->working_directory.len) {
  694.         if (chdir((char *) ccf->working_directory.data) == -1) {
  695.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  696.                           "chdir(\"%s\") failed", ccf->working_directory.data);
  697.             /* fatal */
  698.             exit(2);
  699.         }
  700.     }

  701.     sigemptyset(&set);

  702.     if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
  703.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  704.                       "sigprocmask() failed");
  705.     }

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

  708.     for (i = 0; cycle->modules[i]; i++) {
  709.         if (cycle->modules[i]->init_process) {
  710.             if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
  711.                 /* fatal */
  712.                 exit(2);
  713.             }
  714.         }
  715.     }

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

  717.         if (ngx_processes[n].pid == -1) {
  718.             continue;
  719.         }

  720.         if (n == ngx_process_slot) {
  721.             continue;
  722.         }

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

  726.         if (close(ngx_processes[n].channel[1]) == -1) {
  727.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  728.                           "close() channel failed");
  729.         }
  730.     }

  731.     if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
  732.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  733.                       "close() channel failed");
  734.     }

  735. #if 0
  736.     ngx_last_process = 0;
  737. #endif

  738.     if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
  739.                               ngx_channel_handler)
  740.         == NGX_ERROR)
  741.     {
  742.         /* fatal */
  743.         exit(2);
  744.     }
  745. }


  746. static void
  747. ‌ngx_worker_process_exit(ngx_cycle_t *cycle)
  748. {
  749.     ngx_uint_t         i;
  750.     ngx_connection_t  *c;

  751.     for (i = 0; cycle->modules[i]; i++) {
  752.         if (cycle->modules[i]->exit_process) {
  753.             cycle->modules[i]->exit_process(cycle);
  754.         }
  755.     }

  756.     if (ngx_exiting && !ngx_terminate) {
  757.         c = cycle->connections;
  758.         for (i = 0; i < cycle->connection_n; i++) {
  759.             if (c[i].fd != -1
  760.                 && c[i].read
  761.                 && !c[i].read->accept
  762.                 && !c[i].read->channel
  763.                 && !c[i].read->resolver)
  764.             {
  765.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  766.                               "*%uA open socket #%d left in connection %ui",
  767.                               c[i].number, c[i].fd, i);
  768.                 ngx_debug_quit = 1;
  769.             }
  770.         }
  771.     }

  772.     if (ngx_debug_quit) {
  773.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
  774.         ngx_debug_point();
  775.     }

  776.     /*
  777.      * Copy ngx_cycle->log related data to the special static exit cycle,
  778.      * log, and log file structures enough to allow a signal handler to log.
  779.      * The handler may be called when standard ngx_cycle->log allocated from
  780.      * ngx_cycle->pool is already destroyed.
  781.      */

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

  783.     ngx_exit_log_file.fd = ngx_exit_log.file->fd;
  784.     ngx_exit_log.file = &ngx_exit_log_file;
  785.     ngx_exit_log.next = NULL;
  786.     ngx_exit_log.writer = NULL;

  787.     ngx_exit_cycle.log = &ngx_exit_log;
  788.     ngx_exit_cycle.files = ngx_cycle->files;
  789.     ngx_exit_cycle.files_n = ngx_cycle->files_n;
  790.     ngx_cycle = &ngx_exit_cycle;

  791.     ngx_destroy_pool(cycle->pool);

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

  793.     exit(0);
  794. }


  795. static void
  796. ‌ngx_channel_handler(ngx_event_t *ev)
  797. {
  798.     ngx_int_t          n;
  799.     ngx_channel_t      ch;
  800.     ngx_connection_t  *c;

  801.     if (ev->timedout) {
  802.         ev->timedout = 0;
  803.         return;
  804.     }

  805.     c = ev->data;

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

  807.     for ( ;; ) {

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

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

  810.         if (n == NGX_ERROR) {

  811.             if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
  812.                 ngx_del_conn(c, 0);
  813.             }

  814.             ngx_close_connection(c);
  815.             return;
  816.         }

  817.         if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
  818.             if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  819.                 return;
  820.             }
  821.         }

  822.         if (n == NGX_AGAIN) {
  823.             return;
  824.         }

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

  827.         switch (ch.command) {

  828.         case NGX_CMD_QUIT:
  829.             ngx_quit = 1;
  830.             break;

  831.         case NGX_CMD_TERMINATE:
  832.             ngx_terminate = 1;
  833.             break;

  834.         case NGX_CMD_REOPEN:
  835.             ngx_reopen = 1;
  836.             break;

  837.         case NGX_CMD_OPEN_CHANNEL:

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

  841.             ngx_processes[ch.slot].pid = ch.pid;
  842.             ngx_processes[ch.slot].channel[0] = ch.fd;
  843.             break;

  844.         case NGX_CMD_CLOSE_CHANNEL:

  845.             ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,
  846.                            "close channel s:%i pid:%P our:%P fd:%d",
  847.                            ch.slot, ch.pid, ngx_processes[ch.slot].pid,
  848.                            ngx_processes[ch.slot].channel[0]);

  849.             if (ngx_processes[ch.slot].channel[0] == -1
  850.                 || ngx_processes[ch.slot].pid != ch.pid)
  851.             {
  852.                 break;
  853.             }

  854.             if (close(ngx_processes[ch.slot].channel[0]) == -1) {
  855.                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  856.                               "close() channel failed");
  857.             }

  858.             ngx_processes[ch.slot].channel[0] = -1;
  859.             break;
  860.         }
  861.     }
  862. }


  863. static void
  864. ‌ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
  865. {
  866.     ngx_cache_manager_ctx_t *ctx = data;

  867.     void         *ident[4];
  868.     ngx_event_t   ev;

  869.     /*
  870.      * Set correct process type since closing listening Unix domain socket
  871.      * in a master process also removes the Unix domain socket file.
  872.      */
  873.     ngx_process = NGX_PROCESS_HELPER;

  874.     ngx_close_listening_sockets(cycle);

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

  877.     ngx_worker_process_init(cycle, -1);

  878.     ngx_memzero(&ev, sizeof(ngx_event_t));
  879.     ev.handler = ctx->handler;
  880.     ev.data = ident;
  881.     ev.log = cycle->log;
  882.     ident[3] = (void *) -1;

  883.     ngx_use_accept_mutex = 0;

  884.     ngx_setproctitle(ctx->name);

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

  886.     for ( ;; ) {

  887.         if (ngx_terminate || ngx_quit) {
  888.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  889.             exit(0);
  890.         }

  891.         if (ngx_reopen) {
  892.             ngx_reopen = 0;
  893.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  894.             ngx_reopen_files(cycle, -1);
  895.         }

  896.         ngx_process_events_and_timers(cycle);
  897.     }
  898. }


  899. static void
  900. ‌ngx_cache_manager_process_handler(ngx_event_t *ev)
  901. {
  902.     ngx_uint_t    i;
  903.     ngx_msec_t    next, n;
  904.     ngx_path_t  **path;

  905.     next = 60 * 60 * 1000;

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

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

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

  911.             ngx_time_update();
  912.         }
  913.     }

  914.     if (next == 0) {
  915.         next = 1;
  916.     }

  917.     ngx_add_timer(ev, next);
  918. }


  919. static void
  920. ‌ngx_cache_loader_process_handler(ngx_event_t *ev)
  921. {
  922.     ngx_uint_t     i;
  923.     ngx_path_t   **path;
  924.     ngx_cycle_t   *cycle;

  925.     cycle = (ngx_cycle_t *) ngx_cycle;

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

  928.         if (ngx_terminate || ngx_quit) {
  929.             break;
  930.         }

  931.         if (path[i]->loader) {
  932.             path[i]->loader(path[i]->data);
  933.             ngx_time_update();
  934.         }
  935.     }

  936.     exit(0);
  937. }