src/os/unix/ngx_process_cycle.c - nginx source code

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 (!live && (ngx_terminate || ngx_quit)) {
  135.             ngx_master_process_exit(cycle);
  136.         }

  137.         if (ngx_terminate) {
  138.             if (delay == 0) {
  139.                 delay = 50;
  140.             }

  141.             if (sigio) {
  142.                 sigio--;
  143.                 continue;
  144.             }

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

  146.             if (delay > 1000) {
  147.                 ngx_signal_worker_processes(cycle, SIGKILL);
  148.             } else {
  149.                 ngx_signal_worker_processes(cycle,
  150.                                        ngx_signal_value(NGX_TERMINATE_SIGNAL));
  151.             }

  152.             continue;
  153.         }

  154.         if (ngx_quit) {
  155.             ngx_signal_worker_processes(cycle,
  156.                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  157.             ngx_close_listening_sockets(cycle);

  158.             continue;
  159.         }

  160.         if (ngx_reconfigure) {
  161.             ngx_reconfigure = 0;

  162.             if (ngx_new_binary) {
  163.                 ngx_start_worker_processes(cycle, ccf->worker_processes,
  164.                                            NGX_PROCESS_RESPAWN);
  165.                 ngx_start_cache_manager_processes(cycle, 0);
  166.                 ngx_noaccepting = 0;

  167.                 continue;
  168.             }

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

  170.             cycle = ngx_init_cycle(cycle);
  171.             if (cycle == NULL) {
  172.                 cycle = (ngx_cycle_t *) ngx_cycle;
  173.                 continue;
  174.             }

  175.             ngx_cycle = cycle;
  176.             ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
  177.                                                    ngx_core_module);
  178.             ngx_start_worker_processes(cycle, ccf->worker_processes,
  179.                                        NGX_PROCESS_JUST_RESPAWN);
  180.             ngx_start_cache_manager_processes(cycle, 1);

  181.             /* allow new processes to start */
  182.             ngx_msleep(100);

  183.             live = 1;
  184.             ngx_signal_worker_processes(cycle,
  185.                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  186.         }

  187.         if (ngx_restart) {
  188.             ngx_restart = 0;
  189.             ngx_start_worker_processes(cycle, ccf->worker_processes,
  190.                                        NGX_PROCESS_RESPAWN);
  191.             ngx_start_cache_manager_processes(cycle, 0);
  192.             live = 1;
  193.         }

  194.         if (ngx_reopen) {
  195.             ngx_reopen = 0;
  196.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  197.             ngx_reopen_files(cycle, ccf->user);
  198.             ngx_signal_worker_processes(cycle,
  199.                                         ngx_signal_value(NGX_REOPEN_SIGNAL));
  200.         }

  201.         if (ngx_change_binary) {
  202.             ngx_change_binary = 0;
  203.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
  204.             ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv);
  205.         }

  206.         if (ngx_noaccept) {
  207.             ngx_noaccept = 0;
  208.             ngx_noaccepting = 1;
  209.             ngx_signal_worker_processes(cycle,
  210.                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
  211.         }
  212.     }
  213. }


  214. void
  215. ngx_single_process_cycle(ngx_cycle_t *cycle)
  216. {
  217.     ngx_uint_t  i;

  218.     if (ngx_set_environment(cycle, NULL) == NULL) {
  219.         /* fatal */
  220.         exit(2);
  221.     }

  222.     for (i = 0; cycle->modules[i]; i++) {
  223.         if (cycle->modules[i]->init_process) {
  224.             if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
  225.                 /* fatal */
  226.                 exit(2);
  227.             }
  228.         }
  229.     }

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

  232.         ngx_process_events_and_timers(cycle);

  233.         if (ngx_terminate || ngx_quit) {

  234.             for (i = 0; cycle->modules[i]; i++) {
  235.                 if (cycle->modules[i]->exit_process) {
  236.                     cycle->modules[i]->exit_process(cycle);
  237.                 }
  238.             }

  239.             ngx_master_process_exit(cycle);
  240.         }

  241.         if (ngx_reconfigure) {
  242.             ngx_reconfigure = 0;
  243.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");

  244.             cycle = ngx_init_cycle(cycle);
  245.             if (cycle == NULL) {
  246.                 cycle = (ngx_cycle_t *) ngx_cycle;
  247.                 continue;
  248.             }

  249.             ngx_cycle = cycle;
  250.         }

  251.         if (ngx_reopen) {
  252.             ngx_reopen = 0;
  253.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  254.             ngx_reopen_files(cycle, (ngx_uid_t) -1);
  255.         }
  256.     }
  257. }


  258. static void
  259. ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
  260. {
  261.     ngx_int_t  i;

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

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

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

  266.         ngx_pass_open_channel(cycle);
  267.     }
  268. }


  269. static void
  270. ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
  271. {
  272.     ngx_uint_t    i, manager, loader;
  273.     ngx_path_t  **path;

  274.     manager = 0;
  275.     loader = 0;

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

  278.         if (path[i]->manager) {
  279.             manager = 1;
  280.         }

  281.         if (path[i]->loader) {
  282.             loader = 1;
  283.         }
  284.     }

  285.     if (manager == 0) {
  286.         return;
  287.     }

  288.     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
  289.                       &ngx_cache_manager_ctx, "cache manager process",
  290.                       respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);

  291.     ngx_pass_open_channel(cycle);

  292.     if (loader == 0) {
  293.         return;
  294.     }

  295.     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
  296.                       &ngx_cache_loader_ctx, "cache loader process",
  297.                       respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);

  298.     ngx_pass_open_channel(cycle);
  299. }


  300. static void
  301. ngx_pass_open_channel(ngx_cycle_t *cycle)
  302. {
  303.     ngx_int_t      i;
  304.     ngx_channel_t  ch;

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

  306.     ch.command = NGX_CMD_OPEN_CHANNEL;
  307.     ch.pid = ngx_processes[ngx_process_slot].pid;
  308.     ch.slot = ngx_process_slot;
  309.     ch.fd = ngx_processes[ngx_process_slot].channel[0];

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

  311.         if (i == ngx_process_slot
  312.             || ngx_processes[i].pid == -1
  313.             || ngx_processes[i].channel[0] == -1)
  314.         {
  315.             continue;
  316.         }

  317.         ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  318.                       "pass channel s:%i pid:%P fd:%d to s:%i pid:%P fd:%d",
  319.                       ch.slot, ch.pid, ch.fd,
  320.                       i, ngx_processes[i].pid,
  321.                       ngx_processes[i].channel[0]);

  322.         /* TODO: NGX_AGAIN */

  323.         ngx_write_channel(ngx_processes[i].channel[0],
  324.                           &ch, sizeof(ngx_channel_t), cycle->log);
  325.     }
  326. }


  327. static void
  328. ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
  329. {
  330.     ngx_int_t      i;
  331.     ngx_err_t      err;
  332.     ngx_channel_t  ch;

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

  334. #if (NGX_BROKEN_SCM_RIGHTS)

  335.     ch.command = 0;

  336. #else

  337.     switch (signo) {

  338.     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
  339.         ch.command = NGX_CMD_QUIT;
  340.         break;

  341.     case ngx_signal_value(NGX_TERMINATE_SIGNAL):
  342.         ch.command = NGX_CMD_TERMINATE;
  343.         break;

  344.     case ngx_signal_value(NGX_REOPEN_SIGNAL):
  345.         ch.command = NGX_CMD_REOPEN;
  346.         break;

  347.     default:
  348.         ch.command = 0;
  349.     }

  350. #endif

  351.     ch.fd = -1;


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

  353.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  354.                        "child: %i %P e:%d t:%d d:%d r:%d j:%d",
  355.                        i,
  356.                        ngx_processes[i].pid,
  357.                        ngx_processes[i].exiting,
  358.                        ngx_processes[i].exited,
  359.                        ngx_processes[i].detached,
  360.                        ngx_processes[i].respawn,
  361.                        ngx_processes[i].just_spawn);

  362.         if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
  363.             continue;
  364.         }

  365.         if (ngx_processes[i].just_spawn) {
  366.             ngx_processes[i].just_spawn = 0;
  367.             continue;
  368.         }

  369.         if (ngx_processes[i].exiting
  370.             && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL))
  371.         {
  372.             continue;
  373.         }

  374.         if (ch.command) {
  375.             if (ngx_write_channel(ngx_processes[i].channel[0],
  376.                                   &ch, sizeof(ngx_channel_t), cycle->log)
  377.                 == NGX_OK)
  378.             {
  379.                 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
  380.                     ngx_processes[i].exiting = 1;
  381.                 }

  382.                 continue;
  383.             }
  384.         }

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

  387.         if (kill(ngx_processes[i].pid, signo) == -1) {
  388.             err = ngx_errno;
  389.             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
  390.                           "kill(%P, %d) failed", ngx_processes[i].pid, signo);

  391.             if (err == NGX_ESRCH) {
  392.                 ngx_processes[i].exited = 1;
  393.                 ngx_processes[i].exiting = 0;
  394.                 ngx_reap = 1;
  395.             }

  396.             continue;
  397.         }

  398.         if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
  399.             ngx_processes[i].exiting = 1;
  400.         }
  401.     }
  402. }


  403. static ngx_uint_t
  404. ngx_reap_children(ngx_cycle_t *cycle)
  405. {
  406.     ngx_int_t         i, n;
  407.     ngx_uint_t        live;
  408.     ngx_channel_t     ch;
  409.     ngx_core_conf_t  *ccf;

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

  411.     ch.command = NGX_CMD_CLOSE_CHANNEL;
  412.     ch.fd = -1;

  413.     live = 0;
  414.     for (i = 0; i < ngx_last_process; i++) {

  415.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  416.                        "child: %i %P e:%d t:%d d:%d r:%d j:%d",
  417.                        i,
  418.                        ngx_processes[i].pid,
  419.                        ngx_processes[i].exiting,
  420.                        ngx_processes[i].exited,
  421.                        ngx_processes[i].detached,
  422.                        ngx_processes[i].respawn,
  423.                        ngx_processes[i].just_spawn);

  424.         if (ngx_processes[i].pid == -1) {
  425.             continue;
  426.         }

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

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

  430.                 ngx_processes[i].channel[0] = -1;
  431.                 ngx_processes[i].channel[1] = -1;

  432.                 ch.pid = ngx_processes[i].pid;
  433.                 ch.slot = i;

  434.                 for (n = 0; n < ngx_last_process; n++) {
  435.                     if (ngx_processes[n].exited
  436.                         || ngx_processes[n].pid == -1
  437.                         || ngx_processes[n].channel[0] == -1)
  438.                     {
  439.                         continue;
  440.                     }

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

  444.                     /* TODO: NGX_AGAIN */

  445.                     ngx_write_channel(ngx_processes[n].channel[0],
  446.                                       &ch, sizeof(ngx_channel_t), cycle->log);
  447.                 }
  448.             }

  449.             if (ngx_processes[i].respawn
  450.                 && !ngx_processes[i].exiting
  451.                 && !ngx_terminate
  452.                 && !ngx_quit)
  453.             {
  454.                 if (ngx_spawn_process(cycle, ngx_processes[i].proc,
  455.                                       ngx_processes[i].data,
  456.                                       ngx_processes[i].name, i)
  457.                     == NGX_INVALID_PID)
  458.                 {
  459.                     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  460.                                   "could not respawn %s",
  461.                                   ngx_processes[i].name);
  462.                     continue;
  463.                 }


  464.                 ngx_pass_open_channel(cycle);

  465.                 live = 1;

  466.                 continue;
  467.             }

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

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

  471.                 if (ngx_rename_file((char *) ccf->oldpid.data,
  472.                                     (char *) ccf->pid.data)
  473.                     == NGX_FILE_ERROR)
  474.                 {
  475.                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  476.                                   ngx_rename_file_n " %s back to %s failed "
  477.                                   "after the new binary process \"%s\" exited",
  478.                                   ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
  479.                 }

  480.                 ngx_new_binary = 0;
  481.                 if (ngx_noaccepting) {
  482.                     ngx_restart = 1;
  483.                     ngx_noaccepting = 0;
  484.                 }
  485.             }

  486.             if (i == ngx_last_process - 1) {
  487.                 ngx_last_process--;

  488.             } else {
  489.                 ngx_processes[i].pid = -1;
  490.             }

  491.         } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
  492.             live = 1;
  493.         }
  494.     }

  495.     return live;
  496. }


  497. static void
  498. ngx_master_process_exit(ngx_cycle_t *cycle)
  499. {
  500.     ngx_uint_t  i;

  501.     ngx_delete_pidfile(cycle);

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

  503.     for (i = 0; cycle->modules[i]; i++) {
  504.         if (cycle->modules[i]->exit_master) {
  505.             cycle->modules[i]->exit_master(cycle);
  506.         }
  507.     }

  508.     ngx_close_listening_sockets(cycle);

  509.     /*
  510.      * Copy ngx_cycle->log related data to the special static exit cycle,
  511.      * log, and log file structures enough to allow a signal handler to log.
  512.      * The handler may be called when standard ngx_cycle->log allocated from
  513.      * ngx_cycle->pool is already destroyed.
  514.      */


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

  516.     ngx_exit_log_file.fd = ngx_exit_log.file->fd;
  517.     ngx_exit_log.file = &ngx_exit_log_file;
  518.     ngx_exit_log.next = NULL;
  519.     ngx_exit_log.writer = NULL;

  520.     ngx_exit_cycle.log = &ngx_exit_log;
  521.     ngx_exit_cycle.files = ngx_cycle->files;
  522.     ngx_exit_cycle.files_n = ngx_cycle->files_n;
  523.     ngx_cycle = &ngx_exit_cycle;

  524.     ngx_destroy_pool(cycle->pool);

  525.     exit(0);
  526. }


  527. static void
  528. ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
  529. {
  530.     ngx_int_t worker = (intptr_t) data;

  531.     ngx_process = NGX_PROCESS_WORKER;
  532.     ngx_worker = worker;

  533.     ngx_worker_process_init(cycle, worker);

  534.     ngx_setproctitle("worker process");

  535.     for ( ;; ) {

  536.         if (ngx_exiting) {
  537.             if (ngx_event_no_timers_left() == NGX_OK) {
  538.                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  539.                 ngx_worker_process_exit(cycle);
  540.             }
  541.         }

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

  543.         ngx_process_events_and_timers(cycle);

  544.         if (ngx_terminate) {
  545.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  546.             ngx_worker_process_exit(cycle);
  547.         }

  548.         if (ngx_quit) {
  549.             ngx_quit = 0;
  550.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
  551.                           "gracefully shutting down");
  552.             ngx_setproctitle("worker process is shutting down");

  553.             if (!ngx_exiting) {
  554.                 ngx_exiting = 1;
  555.                 ngx_set_shutdown_timer(cycle);
  556.                 ngx_close_listening_sockets(cycle);
  557.                 ngx_close_idle_connections(cycle);
  558.                 ngx_event_process_posted(cycle, &ngx_posted_events);
  559.             }
  560.         }

  561.         if (ngx_reopen) {
  562.             ngx_reopen = 0;
  563.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  564.             ngx_reopen_files(cycle, -1);
  565.         }
  566.     }
  567. }


  568. static void
  569. ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
  570. {
  571.     sigset_t          set;
  572.     ngx_int_t         n;
  573.     ngx_time_t       *tp;
  574.     ngx_uint_t        i;
  575.     ngx_cpuset_t     *cpu_affinity;
  576.     struct rlimit     rlmt;
  577.     ngx_core_conf_t  *ccf;

  578.     if (ngx_set_environment(cycle, NULL) == NULL) {
  579.         /* fatal */
  580.         exit(2);
  581.     }

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

  583.     if (worker >= 0 && ccf->priority != 0) {
  584.         if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
  585.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  586.                           "setpriority(%d) failed", ccf->priority);
  587.         }
  588.     }

  589.     if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
  590.         rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
  591.         rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;

  592.         if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
  593.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  594.                           "setrlimit(RLIMIT_NOFILE, %i) failed",
  595.                           ccf->rlimit_nofile);
  596.         }
  597.     }

  598.     if (ccf->rlimit_core != NGX_CONF_UNSET) {
  599.         rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
  600.         rlmt.rlim_max = (rlim_t) ccf->rlimit_core;

  601.         if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
  602.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  603.                           "setrlimit(RLIMIT_CORE, %O) failed",
  604.                           ccf->rlimit_core);
  605.         }
  606.     }

  607.     if (geteuid() == 0) {
  608.         if (setgid(ccf->group) == -1) {
  609.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  610.                           "setgid(%d) failed", ccf->group);
  611.             /* fatal */
  612.             exit(2);
  613.         }

  614.         if (initgroups(ccf->username, ccf->group) == -1) {
  615.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  616.                           "initgroups(%s, %d) failed",
  617.                           ccf->username, ccf->group);
  618.         }

  619. #if (NGX_HAVE_PR_SET_KEEPCAPS && NGX_HAVE_CAPABILITIES)
  620.         if (ccf->transparent && ccf->user) {
  621.             if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
  622.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  623.                               "prctl(PR_SET_KEEPCAPS, 1) failed");
  624.                 /* fatal */
  625.                 exit(2);
  626.             }
  627.         }
  628. #endif

  629.         if (setuid(ccf->user) == -1) {
  630.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  631.                           "setuid(%d) failed", ccf->user);
  632.             /* fatal */
  633.             exit(2);
  634.         }

  635. #if (NGX_HAVE_CAPABILITIES)
  636.         if (ccf->transparent && ccf->user) {
  637.             struct __user_cap_data_struct    data;
  638.             struct __user_cap_header_struct  header;

  639.             ngx_memzero(&header, sizeof(struct __user_cap_header_struct));
  640.             ngx_memzero(&data, sizeof(struct __user_cap_data_struct));

  641.             header.version = _LINUX_CAPABILITY_VERSION_1;
  642.             data.effective = CAP_TO_MASK(CAP_NET_RAW);
  643.             data.permitted = data.effective;

  644.             if (syscall(SYS_capset, &header, &data) == -1) {
  645.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  646.                               "capset() failed");
  647.                 /* fatal */
  648.                 exit(2);
  649.             }
  650.         }
  651. #endif
  652.     }

  653.     if (worker >= 0) {
  654.         cpu_affinity = ngx_get_cpu_affinity(worker);

  655.         if (cpu_affinity) {
  656.             ngx_setaffinity(cpu_affinity, cycle->log);
  657.         }
  658.     }

  659. #if (NGX_HAVE_PR_SET_DUMPABLE)

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

  661.     if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
  662.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  663.                       "prctl(PR_SET_DUMPABLE) failed");
  664.     }

  665. #endif

  666.     if (ccf->working_directory.len) {
  667.         if (chdir((char *) ccf->working_directory.data) == -1) {
  668.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  669.                           "chdir(\"%s\") failed", ccf->working_directory.data);
  670.             /* fatal */
  671.             exit(2);
  672.         }
  673.     }

  674.     sigemptyset(&set);

  675.     if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
  676.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  677.                       "sigprocmask() failed");
  678.     }

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

  681.     for (i = 0; cycle->modules[i]; i++) {
  682.         if (cycle->modules[i]->init_process) {
  683.             if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
  684.                 /* fatal */
  685.                 exit(2);
  686.             }
  687.         }
  688.     }

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

  690.         if (ngx_processes[n].pid == -1) {
  691.             continue;
  692.         }

  693.         if (n == ngx_process_slot) {
  694.             continue;
  695.         }

  696.         if (ngx_processes[n].channel[1] == -1) {
  697.             continue;
  698.         }

  699.         if (close(ngx_processes[n].channel[1]) == -1) {
  700.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  701.                           "close() channel failed");
  702.         }
  703.     }

  704.     if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
  705.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  706.                       "close() channel failed");
  707.     }

  708. #if 0
  709.     ngx_last_process = 0;
  710. #endif

  711.     if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
  712.                               ngx_channel_handler)
  713.         == NGX_ERROR)
  714.     {
  715.         /* fatal */
  716.         exit(2);
  717.     }
  718. }


  719. static void
  720. ngx_worker_process_exit(ngx_cycle_t *cycle)
  721. {
  722.     ngx_uint_t         i;
  723.     ngx_connection_t  *c;

  724.     for (i = 0; cycle->modules[i]; i++) {
  725.         if (cycle->modules[i]->exit_process) {
  726.             cycle->modules[i]->exit_process(cycle);
  727.         }
  728.     }

  729.     if (ngx_exiting && !ngx_terminate) {
  730.         c = cycle->connections;
  731.         for (i = 0; i < cycle->connection_n; i++) {
  732.             if (c[i].fd != -1
  733.                 && c[i].read
  734.                 && !c[i].read->accept
  735.                 && !c[i].read->channel
  736.                 && !c[i].read->resolver)
  737.             {
  738.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  739.                               "*%uA open socket #%d left in connection %ui",
  740.                               c[i].number, c[i].fd, i);
  741.                 ngx_debug_quit = 1;
  742.             }
  743.         }
  744.     }

  745.     if (ngx_debug_quit) {
  746.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
  747.         ngx_debug_point();
  748.     }

  749.     /*
  750.      * Copy ngx_cycle->log related data to the special static exit cycle,
  751.      * log, and log file structures enough to allow a signal handler to log.
  752.      * The handler may be called when standard ngx_cycle->log allocated from
  753.      * ngx_cycle->pool is already destroyed.
  754.      */

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

  756.     ngx_exit_log_file.fd = ngx_exit_log.file->fd;
  757.     ngx_exit_log.file = &ngx_exit_log_file;
  758.     ngx_exit_log.next = NULL;
  759.     ngx_exit_log.writer = NULL;

  760.     ngx_exit_cycle.log = &ngx_exit_log;
  761.     ngx_exit_cycle.files = ngx_cycle->files;
  762.     ngx_exit_cycle.files_n = ngx_cycle->files_n;
  763.     ngx_cycle = &ngx_exit_cycle;

  764.     ngx_destroy_pool(cycle->pool);

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

  766.     exit(0);
  767. }


  768. static void
  769. ngx_channel_handler(ngx_event_t *ev)
  770. {
  771.     ngx_int_t          n;
  772.     ngx_channel_t      ch;
  773.     ngx_connection_t  *c;

  774.     if (ev->timedout) {
  775.         ev->timedout = 0;
  776.         return;
  777.     }

  778.     c = ev->data;

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

  780.     for ( ;; ) {

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

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

  783.         if (n == NGX_ERROR) {

  784.             if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
  785.                 ngx_del_conn(c, 0);
  786.             }

  787.             ngx_close_connection(c);
  788.             return;
  789.         }

  790.         if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
  791.             if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  792.                 return;
  793.             }
  794.         }

  795.         if (n == NGX_AGAIN) {
  796.             return;
  797.         }

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

  800.         switch (ch.command) {

  801.         case NGX_CMD_QUIT:
  802.             ngx_quit = 1;
  803.             break;

  804.         case NGX_CMD_TERMINATE:
  805.             ngx_terminate = 1;
  806.             break;

  807.         case NGX_CMD_REOPEN:
  808.             ngx_reopen = 1;
  809.             break;

  810.         case NGX_CMD_OPEN_CHANNEL:

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

  814.             ngx_processes[ch.slot].pid = ch.pid;
  815.             ngx_processes[ch.slot].channel[0] = ch.fd;
  816.             break;

  817.         case NGX_CMD_CLOSE_CHANNEL:

  818.             ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,
  819.                            "close channel s:%i pid:%P our:%P fd:%d",
  820.                            ch.slot, ch.pid, ngx_processes[ch.slot].pid,
  821.                            ngx_processes[ch.slot].channel[0]);

  822.             if (close(ngx_processes[ch.slot].channel[0]) == -1) {
  823.                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  824.                               "close() channel failed");
  825.             }

  826.             ngx_processes[ch.slot].channel[0] = -1;
  827.             break;
  828.         }
  829.     }
  830. }


  831. static void
  832. ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
  833. {
  834.     ngx_cache_manager_ctx_t *ctx = data;

  835.     void         *ident[4];
  836.     ngx_event_t   ev;

  837.     /*
  838.      * Set correct process type since closing listening Unix domain socket
  839.      * in a master process also removes the Unix domain socket file.
  840.      */
  841.     ngx_process = NGX_PROCESS_HELPER;

  842.     ngx_close_listening_sockets(cycle);

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

  845.     ngx_worker_process_init(cycle, -1);

  846.     ngx_memzero(&ev, sizeof(ngx_event_t));
  847.     ev.handler = ctx->handler;
  848.     ev.data = ident;
  849.     ev.log = cycle->log;
  850.     ident[3] = (void *) -1;

  851.     ngx_use_accept_mutex = 0;

  852.     ngx_setproctitle(ctx->name);

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

  854.     for ( ;; ) {

  855.         if (ngx_terminate || ngx_quit) {
  856.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  857.             exit(0);
  858.         }

  859.         if (ngx_reopen) {
  860.             ngx_reopen = 0;
  861.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
  862.             ngx_reopen_files(cycle, -1);
  863.         }

  864.         ngx_process_events_and_timers(cycle);
  865.     }
  866. }


  867. static void
  868. ngx_cache_manager_process_handler(ngx_event_t *ev)
  869. {
  870.     ngx_uint_t    i;
  871.     ngx_msec_t    next, n;
  872.     ngx_path_t  **path;

  873.     next = 60 * 60 * 1000;

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

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

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

  879.             ngx_time_update();
  880.         }
  881.     }

  882.     if (next == 0) {
  883.         next = 1;
  884.     }

  885.     ngx_add_timer(ev, next);
  886. }


  887. static void
  888. ngx_cache_loader_process_handler(ngx_event_t *ev)
  889. {
  890.     ngx_uint_t     i;
  891.     ngx_path_t   **path;
  892.     ngx_cycle_t   *cycle;

  893.     cycle = (ngx_cycle_t *) ngx_cycle;

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

  896.         if (ngx_terminate || ngx_quit) {
  897.             break;
  898.         }

  899.         if (path[i]->loader) {
  900.             path[i]->loader(path[i]->data);
  901.             ngx_time_update();
  902.         }
  903.     }

  904.     exit(0);
  905. }