src/os/win32/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 <nginx.h>


  9. static void ngx_console_init(ngx_cycle_t *cycle);
  10. static int __stdcall ngx_console_handler(u_long type);
  11. static ngx_int_t ngx_create_signal_events(ngx_cycle_t *cycle);
  12. static ngx_int_t ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t type);
  13. static void ngx_reopen_worker_processes(ngx_cycle_t *cycle);
  14. static void ngx_quit_worker_processes(ngx_cycle_t *cycle, ngx_uint_t old);
  15. static void ngx_terminate_worker_processes(ngx_cycle_t *cycle);
  16. static ngx_uint_t ngx_reap_worker(ngx_cycle_t *cycle, HANDLE h);
  17. static void ngx_master_process_exit(ngx_cycle_t *cycle);
  18. static void ngx_worker_process_cycle(ngx_cycle_t *cycle, char *mevn);
  19. static void ngx_worker_process_exit(ngx_cycle_t *cycle);
  20. static ngx_thread_value_t __stdcall ngx_worker_thread(void *data);
  21. static ngx_thread_value_t __stdcall ngx_cache_manager_thread(void *data);
  22. static void ngx_cache_manager_process_handler(void);
  23. static ngx_thread_value_t __stdcall ngx_cache_loader_thread(void *data);


  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. ngx_uint_t     ngx_inherited;
  29. ngx_pid_t      ngx_new_binary;

  30. sig_atomic_t   ngx_terminate;
  31. sig_atomic_t   ngx_quit;
  32. sig_atomic_t   ngx_reopen;
  33. sig_atomic_t   ngx_reconfigure;
  34. ngx_uint_t     ngx_exiting;


  35. HANDLE         ngx_master_process_event;
  36. char           ngx_master_process_event_name[NGX_PROCESS_SYNC_NAME];

  37. static HANDLE  ngx_stop_event;
  38. static char    ngx_stop_event_name[NGX_PROCESS_SYNC_NAME];
  39. static HANDLE  ngx_quit_event;
  40. static char    ngx_quit_event_name[NGX_PROCESS_SYNC_NAME];
  41. static HANDLE  ngx_reopen_event;
  42. static char    ngx_reopen_event_name[NGX_PROCESS_SYNC_NAME];
  43. static HANDLE  ngx_reload_event;
  44. static char    ngx_reload_event_name[NGX_PROCESS_SYNC_NAME];

  45. HANDLE         ngx_cache_manager_mutex;
  46. char           ngx_cache_manager_mutex_name[NGX_PROCESS_SYNC_NAME];
  47. HANDLE         ngx_cache_manager_event;


  48. void
  49. ngx_master_process_cycle(ngx_cycle_t *cycle)
  50. {
  51.     u_long      nev, ev, timeout;
  52.     ngx_err_t   err;
  53.     ngx_int_t   n;
  54.     ngx_msec_t  timer;
  55.     ngx_uint_t  live;
  56.     HANDLE      events[MAXIMUM_WAIT_OBJECTS];

  57.     ngx_sprintf((u_char *) ngx_master_process_event_name,
  58.                 "ngx_master_%s%Z", ngx_unique);

  59.     if (ngx_process == NGX_PROCESS_WORKER) {
  60.         ngx_worker_process_cycle(cycle, ngx_master_process_event_name);
  61.         return;
  62.     }

  63.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "master started");

  64.     ngx_console_init(cycle);

  65.     SetEnvironmentVariable("ngx_unique", ngx_unique);

  66.     ngx_master_process_event = CreateEvent(NULL, 1, 0,
  67.                                            ngx_master_process_event_name);
  68.     if (ngx_master_process_event == NULL) {
  69.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  70.                       "CreateEvent(\"%s\") failed",
  71.                       ngx_master_process_event_name);
  72.         exit(2);
  73.     }

  74.     if (ngx_create_signal_events(cycle) != NGX_OK) {
  75.         exit(2);
  76.     }

  77.     ngx_sprintf((u_char *) ngx_cache_manager_mutex_name,
  78.                 "ngx_cache_manager_mutex_%s%Z", ngx_unique);

  79.     ngx_cache_manager_mutex = CreateMutex(NULL, 0,
  80.                                           ngx_cache_manager_mutex_name);
  81.     if (ngx_cache_manager_mutex == NULL) {
  82.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  83.                    "CreateMutex(\"%s\") failed", ngx_cache_manager_mutex_name);
  84.         exit(2);
  85.     }


  86.     events[0] = ngx_stop_event;
  87.     events[1] = ngx_quit_event;
  88.     events[2] = ngx_reopen_event;
  89.     events[3] = ngx_reload_event;

  90.     ngx_close_listening_sockets(cycle);

  91.     if (ngx_start_worker_processes(cycle, NGX_PROCESS_RESPAWN) == 0) {
  92.         exit(2);
  93.     }

  94.     timer = 0;
  95.     timeout = INFINITE;

  96.     for ( ;; ) {

  97.         nev = 4;
  98.         for (n = 0; n < ngx_last_process; n++) {
  99.             if (ngx_processes[n].handle) {
  100.                 events[nev++] = ngx_processes[n].handle;
  101.             }
  102.         }

  103.         if (timer) {
  104.             timeout = timer > ngx_current_msec ? timer - ngx_current_msec : 0;
  105.         }

  106.         ev = WaitForMultipleObjects(nev, events, 0, timeout);

  107.         err = ngx_errno;
  108.         ngx_time_update();

  109.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  110.                        "master WaitForMultipleObjects: %ul", ev);

  111.         if (ev == WAIT_OBJECT_0) {
  112.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");

  113.             if (ResetEvent(ngx_stop_event) == 0) {
  114.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  115.                               "ResetEvent(\"%s\") failed", ngx_stop_event_name);
  116.             }

  117.             if (timer == 0) {
  118.                 timer = ngx_current_msec + 5000;
  119.             }

  120.             ngx_terminate = 1;
  121.             ngx_quit_worker_processes(cycle, 0);

  122.             continue;
  123.         }

  124.         if (ev == WAIT_OBJECT_0 + 1) {
  125.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "shutting down");

  126.             if (ResetEvent(ngx_quit_event) == 0) {
  127.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  128.                               "ResetEvent(\"%s\") failed", ngx_quit_event_name);
  129.             }

  130.             ngx_quit = 1;
  131.             ngx_quit_worker_processes(cycle, 0);

  132.             continue;
  133.         }

  134.         if (ev == WAIT_OBJECT_0 + 2) {
  135.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");

  136.             if (ResetEvent(ngx_reopen_event) == 0) {
  137.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  138.                               "ResetEvent(\"%s\") failed",
  139.                               ngx_reopen_event_name);
  140.             }

  141.             ngx_reopen_files(cycle, -1);
  142.             ngx_reopen_worker_processes(cycle);

  143.             continue;
  144.         }

  145.         if (ev == WAIT_OBJECT_0 + 3) {
  146.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");

  147.             if (ResetEvent(ngx_reload_event) == 0) {
  148.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  149.                               "ResetEvent(\"%s\") failed",
  150.                               ngx_reload_event_name);
  151.             }

  152.             cycle = ngx_init_cycle(cycle);
  153.             if (cycle == NULL) {
  154.                 cycle = (ngx_cycle_t *) ngx_cycle;
  155.                 continue;
  156.             }

  157.             ngx_cycle = cycle;

  158.             ngx_close_listening_sockets(cycle);

  159.             if (ngx_start_worker_processes(cycle, NGX_PROCESS_JUST_RESPAWN)) {
  160.                 ngx_quit_worker_processes(cycle, 1);
  161.             }

  162.             continue;
  163.         }

  164.         if (ev > WAIT_OBJECT_0 + 3 && ev < WAIT_OBJECT_0 + nev) {

  165.             ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "reap worker");

  166.             live = ngx_reap_worker(cycle, events[ev]);

  167.             if (!live && (ngx_terminate || ngx_quit)) {
  168.                 ngx_master_process_exit(cycle);
  169.             }

  170.             continue;
  171.         }

  172.         if (ev == WAIT_TIMEOUT) {
  173.             ngx_terminate_worker_processes(cycle);

  174.             ngx_master_process_exit(cycle);
  175.         }

  176.         if (ev == WAIT_FAILED) {
  177.             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
  178.                           "WaitForMultipleObjects() failed");

  179.             continue;
  180.         }

  181.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  182.             "WaitForMultipleObjects() returned unexpected value %ul", ev);
  183.     }
  184. }


  185. static void
  186. ngx_console_init(ngx_cycle_t *cycle)
  187. {
  188.     ngx_core_conf_t  *ccf;

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

  190.     if (ccf->daemon) {
  191.         if (FreeConsole() == 0) {
  192.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  193.                           "FreeConsole() failed");
  194.         }

  195.         return;
  196.     }

  197.     if (SetConsoleCtrlHandler(ngx_console_handler, 1) == 0) {
  198.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  199.                       "SetConsoleCtrlHandler() failed");
  200.     }
  201. }


  202. static int __stdcall
  203. ngx_console_handler(u_long type)
  204. {
  205.     char  *msg;

  206.     switch (type) {

  207.     case CTRL_C_EVENT:
  208.         msg = "Ctrl-C pressed, exiting";
  209.         break;

  210.     case CTRL_BREAK_EVENT:
  211.         msg = "Ctrl-Break pressed, exiting";
  212.         break;

  213.     case CTRL_CLOSE_EVENT:
  214.         msg = "console closing, exiting";
  215.         break;

  216.     case CTRL_LOGOFF_EVENT:
  217.         msg = "user logs off, exiting";
  218.         break;

  219.     default:
  220.         return 0;
  221.     }

  222.     ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, msg);

  223.     if (ngx_stop_event == NULL) {
  224.         return 1;
  225.     }

  226.     if (SetEvent(ngx_stop_event) == 0) {
  227.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  228.                       "SetEvent(\"%s\") failed", ngx_stop_event_name);
  229.     }

  230.     return 1;
  231. }


  232. static ngx_int_t
  233. ngx_create_signal_events(ngx_cycle_t *cycle)
  234. {
  235.     ngx_sprintf((u_char *) ngx_stop_event_name,
  236.                 "Global\\ngx_stop_%s%Z", ngx_unique);

  237.     ngx_stop_event = CreateEvent(NULL, 1, 0, ngx_stop_event_name);
  238.     if (ngx_stop_event == NULL) {
  239.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  240.                       "CreateEvent(\"%s\") failed", ngx_stop_event_name);
  241.         return NGX_ERROR;
  242.     }


  243.     ngx_sprintf((u_char *) ngx_quit_event_name,
  244.                 "Global\\ngx_quit_%s%Z", ngx_unique);

  245.     ngx_quit_event = CreateEvent(NULL, 1, 0, ngx_quit_event_name);
  246.     if (ngx_quit_event == NULL) {
  247.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  248.                       "CreateEvent(\"%s\") failed", ngx_quit_event_name);
  249.         return NGX_ERROR;
  250.     }


  251.     ngx_sprintf((u_char *) ngx_reopen_event_name,
  252.                 "Global\\ngx_reopen_%s%Z", ngx_unique);

  253.     ngx_reopen_event = CreateEvent(NULL, 1, 0, ngx_reopen_event_name);
  254.     if (ngx_reopen_event == NULL) {
  255.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  256.                       "CreateEvent(\"%s\") failed", ngx_reopen_event_name);
  257.         return NGX_ERROR;
  258.     }


  259.     ngx_sprintf((u_char *) ngx_reload_event_name,
  260.                 "Global\\ngx_reload_%s%Z", ngx_unique);

  261.     ngx_reload_event = CreateEvent(NULL, 1, 0, ngx_reload_event_name);
  262.     if (ngx_reload_event == NULL) {
  263.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  264.                       "CreateEvent(\"%s\") failed", ngx_reload_event_name);
  265.         return NGX_ERROR;
  266.     }

  267.     return NGX_OK;
  268. }


  269. static ngx_int_t
  270. ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t type)
  271. {
  272.     ngx_int_t         n;
  273.     ngx_core_conf_t  *ccf;

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

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

  276.     for (n = 0; n < ccf->worker_processes; n++) {
  277.         if (ngx_spawn_process(cycle, "worker", type) == NGX_INVALID_PID) {
  278.             break;
  279.         }
  280.     }

  281.     return n;
  282. }


  283. static void
  284. ngx_reopen_worker_processes(ngx_cycle_t *cycle)
  285. {
  286.     ngx_int_t  n;

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

  288.         if (ngx_processes[n].handle == NULL) {
  289.             continue;
  290.         }

  291.         if (SetEvent(ngx_processes[n].reopen) == 0) {
  292.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  293.                           "SetEvent(\"%s\") failed",
  294.                           ngx_processes[n].reopen_event);
  295.         }
  296.     }
  297. }


  298. static void
  299. ngx_quit_worker_processes(ngx_cycle_t *cycle, ngx_uint_t old)
  300. {
  301.     ngx_int_t  n;

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

  303.         ngx_log_debug5(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  304.                        "process: %d %P %p e:%d j:%d",
  305.                        n,
  306.                        ngx_processes[n].pid,
  307.                        ngx_processes[n].handle,
  308.                        ngx_processes[n].exiting,
  309.                        ngx_processes[n].just_spawn);

  310.         if (old && ngx_processes[n].just_spawn) {
  311.             ngx_processes[n].just_spawn = 0;
  312.             continue;
  313.         }

  314.         if (ngx_processes[n].handle == NULL) {
  315.             continue;
  316.         }

  317.         if (SetEvent(ngx_processes[n].quit) == 0) {
  318.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  319.                           "SetEvent(\"%s\") failed",
  320.                           ngx_processes[n].quit_event);
  321.         }

  322.         ngx_processes[n].exiting = 1;
  323.     }
  324. }


  325. static void
  326. ngx_terminate_worker_processes(ngx_cycle_t *cycle)
  327. {
  328.     ngx_int_t  n;

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

  330.         if (ngx_processes[n].handle == NULL) {
  331.             continue;
  332.         }

  333.         if (TerminateProcess(ngx_processes[n].handle, 0) == 0) {
  334.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  335.                           "TerminateProcess(\"%p\") failed",
  336.                           ngx_processes[n].handle);
  337.         }

  338.         ngx_processes[n].exiting = 1;

  339.         ngx_close_handle(ngx_processes[n].reopen);
  340.         ngx_close_handle(ngx_processes[n].quit);
  341.         ngx_close_handle(ngx_processes[n].term);
  342.         ngx_close_handle(ngx_processes[n].handle);
  343.     }
  344. }


  345. static ngx_uint_t
  346. ngx_reap_worker(ngx_cycle_t *cycle, HANDLE h)
  347. {
  348.     u_long     code;
  349.     ngx_int_t  n;

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

  351.         if (ngx_processes[n].handle != h) {
  352.             continue;
  353.         }

  354.         if (GetExitCodeProcess(h, &code) == 0) {
  355.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  356.                           "GetExitCodeProcess(%P) failed",
  357.                           ngx_processes[n].pid);
  358.         }

  359.         ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
  360.                       "%s process %P exited with code %Xl",
  361.                       ngx_processes[n].name, ngx_processes[n].pid, code);

  362.         ngx_close_handle(ngx_processes[n].reopen);
  363.         ngx_close_handle(ngx_processes[n].quit);
  364.         ngx_close_handle(ngx_processes[n].term);
  365.         ngx_close_handle(h);

  366.         ngx_processes[n].handle = NULL;
  367.         ngx_processes[n].term = NULL;
  368.         ngx_processes[n].quit = NULL;
  369.         ngx_processes[n].reopen = NULL;

  370.         if (!ngx_processes[n].exiting && !ngx_terminate && !ngx_quit) {

  371.             if (ngx_spawn_process(cycle, ngx_processes[n].name, n)
  372.                 == NGX_INVALID_PID)
  373.             {
  374.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  375.                               "could not respawn %s", ngx_processes[n].name);

  376.                 if (n == ngx_last_process - 1) {
  377.                     ngx_last_process--;
  378.                 }
  379.             }
  380.         }

  381.         goto found;
  382.     }

  383.     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unknown process handle %p", h);

  384. found:

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

  386.         ngx_log_debug5(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  387.                        "process: %d %P %p e:%d j:%d",
  388.                        n,
  389.                        ngx_processes[n].pid,
  390.                        ngx_processes[n].handle,
  391.                        ngx_processes[n].exiting,
  392.                        ngx_processes[n].just_spawn);

  393.         if (ngx_processes[n].handle) {
  394.             return 1;
  395.         }
  396.     }

  397.     return 0;
  398. }


  399. static void
  400. ngx_master_process_exit(ngx_cycle_t *cycle)
  401. {
  402.     ngx_uint_t  i;

  403.     ngx_delete_pidfile(cycle);

  404.     ngx_close_handle(ngx_cache_manager_mutex);
  405.     ngx_close_handle(ngx_stop_event);
  406.     ngx_close_handle(ngx_quit_event);
  407.     ngx_close_handle(ngx_reopen_event);
  408.     ngx_close_handle(ngx_reload_event);
  409.     ngx_close_handle(ngx_master_process_event);

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

  411.     for (i = 0; cycle->modules[i]; i++) {
  412.         if (cycle->modules[i]->exit_master) {
  413.             cycle->modules[i]->exit_master(cycle);
  414.         }
  415.     }

  416.     ngx_destroy_pool(cycle->pool);

  417.     exit(0);
  418. }


  419. static void
  420. ngx_worker_process_cycle(ngx_cycle_t *cycle, char *mevn)
  421. {
  422.     char        wtevn[NGX_PROCESS_SYNC_NAME];
  423.     char        wqevn[NGX_PROCESS_SYNC_NAME];
  424.     char        wroevn[NGX_PROCESS_SYNC_NAME];
  425.     HANDLE      mev, events[3];
  426.     u_long      nev, ev;
  427.     ngx_err_t   err;
  428.     ngx_tid_t   wtid, cmtid, cltid;
  429.     ngx_log_t  *log;

  430.     log = cycle->log;

  431.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "worker started");

  432.     ngx_sprintf((u_char *) wtevn, "ngx_worker_term_%P%Z", ngx_pid);
  433.     events[0] = CreateEvent(NULL, 1, 0, wtevn);
  434.     if (events[0] == NULL) {
  435.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  436.                       "CreateEvent(\"%s\") failed", wtevn);
  437.         goto failed;
  438.     }

  439.     ngx_sprintf((u_char *) wqevn, "ngx_worker_quit_%P%Z", ngx_pid);
  440.     events[1] = CreateEvent(NULL, 1, 0, wqevn);
  441.     if (events[1] == NULL) {
  442.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  443.                       "CreateEvent(\"%s\") failed", wqevn);
  444.         goto failed;
  445.     }

  446.     ngx_sprintf((u_char *) wroevn, "ngx_worker_reopen_%P%Z", ngx_pid);
  447.     events[2] = CreateEvent(NULL, 1, 0, wroevn);
  448.     if (events[2] == NULL) {
  449.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  450.                       "CreateEvent(\"%s\") failed", wroevn);
  451.         goto failed;
  452.     }

  453.     mev = OpenEvent(EVENT_MODIFY_STATE, 0, mevn);
  454.     if (mev == NULL) {
  455.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  456.                       "OpenEvent(\"%s\") failed", mevn);
  457.         goto failed;
  458.     }

  459.     if (SetEvent(mev) == 0) {
  460.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  461.                       "SetEvent(\"%s\") failed", mevn);
  462.         goto failed;
  463.     }


  464.     ngx_sprintf((u_char *) ngx_cache_manager_mutex_name,
  465.                 "ngx_cache_manager_mutex_%s%Z", ngx_unique);

  466.     ngx_cache_manager_mutex = OpenMutex(SYNCHRONIZE, 0,
  467.                                         ngx_cache_manager_mutex_name);
  468.     if (ngx_cache_manager_mutex == NULL) {
  469.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  470.                       "OpenMutex(\"%s\") failed", ngx_cache_manager_mutex_name);
  471.         goto failed;
  472.     }

  473.     ngx_cache_manager_event = CreateEvent(NULL, 1, 0, NULL);
  474.     if (ngx_cache_manager_event == NULL) {
  475.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  476.                       "CreateEvent(\"ngx_cache_manager_event\") failed");
  477.         goto failed;
  478.     }


  479.     if (ngx_create_thread(&wtid, ngx_worker_thread, NULL, log) != 0) {
  480.         goto failed;
  481.     }

  482.     if (ngx_create_thread(&cmtid, ngx_cache_manager_thread, NULL, log) != 0) {
  483.         goto failed;
  484.     }

  485.     if (ngx_create_thread(&cltid, ngx_cache_loader_thread, NULL, log) != 0) {
  486.         goto failed;
  487.     }

  488.     for ( ;; ) {
  489.         ev = WaitForMultipleObjects(3, events, 0, INFINITE);

  490.         err = ngx_errno;
  491.         ngx_time_update();

  492.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
  493.                        "worker WaitForMultipleObjects: %ul", ev);

  494.         if (ev == WAIT_OBJECT_0) {
  495.             ngx_terminate = 1;
  496.             ngx_log_error(NGX_LOG_NOTICE, log, 0, "exiting");

  497.             if (ResetEvent(events[0]) == 0) {
  498.                 ngx_log_error(NGX_LOG_ALERT, log, 0,
  499.                               "ResetEvent(\"%s\") failed", wtevn);
  500.             }

  501.             break;
  502.         }

  503.         if (ev == WAIT_OBJECT_0 + 1) {
  504.             ngx_quit = 1;
  505.             ngx_log_error(NGX_LOG_NOTICE, log, 0, "gracefully shutting down");
  506.             break;
  507.         }

  508.         if (ev == WAIT_OBJECT_0 + 2) {
  509.             ngx_reopen = 1;
  510.             ngx_log_error(NGX_LOG_NOTICE, log, 0, "reopening logs");

  511.             if (ResetEvent(events[2]) == 0) {
  512.                 ngx_log_error(NGX_LOG_ALERT, log, 0,
  513.                               "ResetEvent(\"%s\") failed", wroevn);
  514.             }

  515.             continue;
  516.         }

  517.         if (ev == WAIT_FAILED) {
  518.             ngx_log_error(NGX_LOG_ALERT, log, err,
  519.                           "WaitForMultipleObjects() failed");

  520.             goto failed;
  521.         }
  522.     }

  523.     /* wait threads */

  524.     if (SetEvent(ngx_cache_manager_event) == 0) {
  525.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  526.                       "SetEvent(\"ngx_cache_manager_event\") failed");
  527.     }

  528.     events[1] = wtid;
  529.     events[2] = cmtid;

  530.     nev = 3;

  531.     for ( ;; ) {
  532.         ev = WaitForMultipleObjects(nev, events, 0, INFINITE);

  533.         err = ngx_errno;
  534.         ngx_time_update();

  535.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
  536.                        "worker exit WaitForMultipleObjects: %ul", ev);

  537.         if (ev == WAIT_OBJECT_0) {
  538.             break;
  539.         }

  540.         if (ev == WAIT_OBJECT_0 + 1) {
  541.             if (nev == 2) {
  542.                 break;
  543.             }

  544.             events[1] = events[2];
  545.             nev = 2;
  546.             continue;
  547.         }

  548.         if (ev == WAIT_OBJECT_0 + 2) {
  549.             nev = 2;
  550.             continue;
  551.         }

  552.         if (ev == WAIT_FAILED) {
  553.             ngx_log_error(NGX_LOG_ALERT, log, err,
  554.                           "WaitForMultipleObjects() failed");
  555.             break;
  556.         }
  557.     }

  558.     ngx_close_handle(ngx_cache_manager_event);
  559.     ngx_close_handle(events[0]);
  560.     ngx_close_handle(events[1]);
  561.     ngx_close_handle(events[2]);
  562.     ngx_close_handle(mev);

  563.     ngx_worker_process_exit(cycle);

  564. failed:

  565.     exit(2);
  566. }


  567. static ngx_thread_value_t __stdcall
  568. ngx_worker_thread(void *data)
  569. {
  570.     ngx_int_t     n;
  571.     ngx_time_t   *tp;
  572.     ngx_cycle_t  *cycle;

  573.     tp = ngx_timeofday();
  574.     srand((ngx_pid << 16) ^ (unsigned) tp->sec ^ tp->msec);

  575.     cycle = (ngx_cycle_t *) ngx_cycle;

  576.     for (n = 0; cycle->modules[n]; n++) {
  577.         if (cycle->modules[n]->init_process) {
  578.             if (cycle->modules[n]->init_process(cycle) == NGX_ERROR) {
  579.                 /* fatal */
  580.                 exit(2);
  581.             }
  582.         }
  583.     }

  584.     while (!ngx_quit) {

  585.         if (ngx_exiting) {
  586.             if (ngx_event_no_timers_left() == NGX_OK) {
  587.                 break;
  588.             }
  589.         }

  590.         ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "worker cycle");

  591.         ngx_process_events_and_timers(cycle);

  592.         if (ngx_terminate) {
  593.             return 0;
  594.         }

  595.         if (ngx_quit) {
  596.             ngx_quit = 0;

  597.             if (!ngx_exiting) {
  598.                 ngx_exiting = 1;
  599.                 ngx_set_shutdown_timer(cycle);
  600.                 ngx_close_listening_sockets(cycle);
  601.                 ngx_close_idle_connections(cycle);
  602.                 ngx_event_process_posted(cycle, &ngx_posted_events);
  603.             }
  604.         }

  605.         if (ngx_reopen) {
  606.             ngx_reopen = 0;
  607.             ngx_reopen_files(cycle, -1);
  608.         }
  609.     }

  610.     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");

  611.     return 0;
  612. }


  613. static void
  614. ngx_worker_process_exit(ngx_cycle_t *cycle)
  615. {
  616.     ngx_uint_t         i;
  617.     ngx_connection_t  *c;

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

  619.     for (i = 0; cycle->modules[i]; i++) {
  620.         if (cycle->modules[i]->exit_process) {
  621.             cycle->modules[i]->exit_process(cycle);
  622.         }
  623.     }

  624.     if (ngx_exiting && !ngx_terminate) {
  625.         c = cycle->connections;
  626.         for (i = 0; i < cycle->connection_n; i++) {
  627.             if (c[i].fd != (ngx_socket_t) -1
  628.                 && c[i].read
  629.                 && !c[i].read->accept
  630.                 && !c[i].read->channel
  631.                 && !c[i].read->resolver)
  632.             {
  633.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  634.                               "*%uA open socket #%d left in connection %ui",
  635.                               c[i].number, c[i].fd, i);
  636.             }
  637.         }
  638.     }

  639.     ngx_destroy_pool(cycle->pool);

  640.     exit(0);
  641. }


  642. static ngx_thread_value_t __stdcall
  643. ngx_cache_manager_thread(void *data)
  644. {
  645.     u_long        ev;
  646.     HANDLE        events[2];
  647.     ngx_err_t     err;
  648.     ngx_cycle_t  *cycle;

  649.     cycle = (ngx_cycle_t *) ngx_cycle;

  650.     events[0] = ngx_cache_manager_event;
  651.     events[1] = ngx_cache_manager_mutex;

  652.     for ( ;; ) {
  653.         ev = WaitForMultipleObjects(2, events, 0, INFINITE);

  654.         err = ngx_errno;
  655.         ngx_time_update();

  656.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  657.                        "cache manager WaitForMultipleObjects: %ul", ev);

  658.         if (ev == WAIT_FAILED) {
  659.             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
  660.                           "WaitForMultipleObjects() failed");
  661.         }

  662.         /*
  663.          * ev == WAIT_OBJECT_0
  664.          * ev == WAIT_OBJECT_0 + 1
  665.          * ev == WAIT_ABANDONED_0 + 1
  666.          */

  667.         if (ngx_terminate || ngx_quit || ngx_exiting) {
  668.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  669.             return 0;
  670.         }

  671.         break;
  672.     }

  673.     for ( ;; ) {

  674.         if (ngx_terminate || ngx_quit || ngx_exiting) {
  675.             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
  676.             break;
  677.         }

  678.         ngx_cache_manager_process_handler();
  679.     }

  680.     if (ReleaseMutex(ngx_cache_manager_mutex) == 0) {
  681.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  682.                       "ReleaseMutex() failed");
  683.     }

  684.     return 0;
  685. }


  686. static void
  687. ngx_cache_manager_process_handler(void)
  688. {
  689.     u_long        ev;
  690.     ngx_uint_t    i;
  691.     ngx_msec_t    next, n;
  692.     ngx_path_t  **path;

  693.     next = 60 * 60 * 1000;

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

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

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

  699.             ngx_time_update();
  700.         }
  701.     }

  702.     if (next == 0) {
  703.         next = 1;
  704.     }

  705.     ev = WaitForSingleObject(ngx_cache_manager_event, (u_long) next);

  706.     if (ev != WAIT_TIMEOUT) {

  707.         ngx_time_update();

  708.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
  709.                        "cache manager WaitForSingleObject: %ul", ev);
  710.     }
  711. }


  712. static ngx_thread_value_t __stdcall
  713. ngx_cache_loader_thread(void *data)
  714. {
  715.     ngx_uint_t     i;
  716.     ngx_path_t   **path;
  717.     ngx_cycle_t   *cycle;

  718.     ngx_msleep(60000);

  719.     cycle = (ngx_cycle_t *) ngx_cycle;

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

  722.         if (ngx_terminate || ngx_quit || ngx_exiting) {
  723.             break;
  724.         }

  725.         if (path[i]->loader) {
  726.             path[i]->loader(path[i]->data);
  727.             ngx_time_update();
  728.         }
  729.     }

  730.     return 0;
  731. }


  732. void
  733. ngx_single_process_cycle(ngx_cycle_t *cycle)
  734. {
  735.     ngx_tid_t  tid;

  736.     ngx_console_init(cycle);

  737.     if (ngx_create_signal_events(cycle) != NGX_OK) {
  738.         exit(2);
  739.     }

  740.     if (ngx_create_thread(&tid, ngx_worker_thread, NULL, cycle->log) != 0) {
  741.         /* fatal */
  742.         exit(2);
  743.     }

  744.     /* STUB */
  745.     WaitForSingleObject(ngx_stop_event, INFINITE);
  746. }


  747. ngx_int_t
  748. ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_pid_t pid)
  749. {
  750.     HANDLE     ev;
  751.     ngx_int_t  rc;
  752.     char       evn[NGX_PROCESS_SYNC_NAME];

  753.     ngx_sprintf((u_char *) evn, "Global\\ngx_%s_%P%Z", sig, pid);

  754.     ev = OpenEvent(EVENT_MODIFY_STATE, 0, evn);
  755.     if (ev == NULL) {
  756.         ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
  757.                       "OpenEvent(\"%s\") failed", evn);
  758.         return 1;
  759.     }

  760.     if (SetEvent(ev) == 0) {
  761.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  762.                       "SetEvent(\"%s\") failed", evn);
  763.         rc = 1;

  764.     } else {
  765.         rc = 0;
  766.     }

  767.     ngx_close_handle(ev);

  768.     return rc;
  769. }


  770. void
  771. ngx_close_handle(HANDLE h)
  772. {
  773.     if (CloseHandle(h) == 0) {
  774.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
  775.                       "CloseHandle(%p) failed", h);
  776.     }
  777. }