src/os/win32/ngx_process.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. int              ngx_argc;
  8. char           **ngx_argv;
  9. char           **ngx_os_argv;

  10. ngx_int_t        ngx_last_process;
  11. ngx_process_t    ngx_processes[NGX_MAX_PROCESSES];


  12. ngx_pid_t
  13. ngx_spawn_process(ngx_cycle_t *cycle, char *name, ngx_int_t respawn)
  14. {
  15.     u_long          rc, n, code;
  16.     ngx_int_t       s;
  17.     ngx_pid_t       pid;
  18.     ngx_exec_ctx_t  ctx;
  19.     HANDLE          events[2];
  20.     char            file[MAX_PATH + 1];

  21.     if (respawn >= 0) {
  22.         s = respawn;

  23.     } else {
  24.         for (s = 0; s < ngx_last_process; s++) {
  25.             if (ngx_processes[s].handle == NULL) {
  26.                 break;
  27.             }
  28.         }

  29.         if (s == NGX_MAX_PROCESSES) {
  30.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  31.                           "no more than %d processes can be spawned",
  32.                           NGX_MAX_PROCESSES);
  33.             return NGX_INVALID_PID;
  34.         }
  35.     }

  36.     n = GetModuleFileName(NULL, file, MAX_PATH);

  37.     if (n == 0) {
  38.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  39.                       "GetModuleFileName() failed");
  40.         return NGX_INVALID_PID;
  41.     }

  42.     file[n] = '\0';

  43.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  44.                    "GetModuleFileName: \"%s\"", file);

  45.     ctx.path = file;
  46.     ctx.name = name;
  47.     ctx.args = GetCommandLine();
  48.     ctx.argv = NULL;
  49.     ctx.envp = NULL;

  50.     pid = ngx_execute(cycle, &ctx);

  51.     if (pid == NGX_INVALID_PID) {
  52.         return pid;
  53.     }

  54.     ngx_memzero(&ngx_processes[s], sizeof(ngx_process_t));

  55.     ngx_processes[s].handle = ctx.child;
  56.     ngx_processes[s].pid = pid;
  57.     ngx_processes[s].name = name;

  58.     ngx_sprintf(ngx_processes[s].term_event, "ngx_%s_term_%P%Z", name, pid);
  59.     ngx_sprintf(ngx_processes[s].quit_event, "ngx_%s_quit_%P%Z", name, pid);
  60.     ngx_sprintf(ngx_processes[s].reopen_event, "ngx_%s_reopen_%P%Z",
  61.                 name, pid);

  62.     events[0] = ngx_master_process_event;
  63.     events[1] = ctx.child;

  64.     rc = WaitForMultipleObjects(2, events, 0, 5000);

  65.     ngx_time_update();

  66.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
  67.                    "WaitForMultipleObjects: %ul", rc);

  68.     switch (rc) {

  69.     case WAIT_OBJECT_0:

  70.         ngx_processes[s].term = OpenEvent(EVENT_MODIFY_STATE, 0,
  71.                                           (char *) ngx_processes[s].term_event);
  72.         if (ngx_processes[s].term == NULL) {
  73.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  74.                           "OpenEvent(\"%s\") failed",
  75.                           ngx_processes[s].term_event);
  76.             goto failed;
  77.         }

  78.         ngx_processes[s].quit = OpenEvent(EVENT_MODIFY_STATE, 0,
  79.                                           (char *) ngx_processes[s].quit_event);
  80.         if (ngx_processes[s].quit == NULL) {
  81.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  82.                           "OpenEvent(\"%s\") failed",
  83.                           ngx_processes[s].quit_event);
  84.             goto failed;
  85.         }

  86.         ngx_processes[s].reopen = OpenEvent(EVENT_MODIFY_STATE, 0,
  87.                                        (char *) ngx_processes[s].reopen_event);
  88.         if (ngx_processes[s].reopen == NULL) {
  89.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  90.                           "OpenEvent(\"%s\") failed",
  91.                           ngx_processes[s].reopen_event);
  92.             goto failed;
  93.         }

  94.         if (ResetEvent(ngx_master_process_event) == 0) {
  95.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  96.                           "ResetEvent(\"%s\") failed",
  97.                           ngx_master_process_event_name);
  98.             goto failed;
  99.         }

  100.         break;

  101.     case WAIT_OBJECT_0 + 1:
  102.         if (GetExitCodeProcess(ctx.child, &code) == 0) {
  103.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  104.                           "GetExitCodeProcess(%P) failed", pid);
  105.         }

  106.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  107.                       "%s process %P exited with code %Xl",
  108.                       name, pid, code);

  109.         goto failed;

  110.     case WAIT_TIMEOUT:
  111.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  112.                       "the event \"%s\" was not signaled for 5s",
  113.                       ngx_master_process_event_name);
  114.         goto failed;

  115.     case WAIT_FAILED:
  116.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  117.                       "WaitForSingleObject(\"%s\") failed",
  118.                       ngx_master_process_event_name);

  119.         goto failed;
  120.     }

  121.     if (respawn >= 0) {
  122.         return pid;
  123.     }

  124.     switch (respawn) {

  125.     case NGX_PROCESS_RESPAWN:
  126.         ngx_processes[s].just_spawn = 0;
  127.         break;

  128.     case NGX_PROCESS_JUST_RESPAWN:
  129.         ngx_processes[s].just_spawn = 1;
  130.         break;
  131.     }

  132.     if (s == ngx_last_process) {
  133.         ngx_last_process++;
  134.     }

  135.     return pid;

  136. failed:

  137.     if (ngx_processes[s].reopen) {
  138.         ngx_close_handle(ngx_processes[s].reopen);
  139.     }

  140.     if (ngx_processes[s].quit) {
  141.         ngx_close_handle(ngx_processes[s].quit);
  142.     }

  143.     if (ngx_processes[s].term) {
  144.         ngx_close_handle(ngx_processes[s].term);
  145.     }

  146.     TerminateProcess(ngx_processes[s].handle, 2);

  147.     if (ngx_processes[s].handle) {
  148.         ngx_close_handle(ngx_processes[s].handle);
  149.         ngx_processes[s].handle = NULL;
  150.     }

  151.     return NGX_INVALID_PID;
  152. }


  153. ngx_pid_t
  154. ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
  155. {
  156.     STARTUPINFO          si;
  157.     PROCESS_INFORMATION  pi;

  158.     ngx_memzero(&si, sizeof(STARTUPINFO));
  159.     si.cb = sizeof(STARTUPINFO);

  160.     ngx_memzero(&pi, sizeof(PROCESS_INFORMATION));

  161.     if (CreateProcess(ctx->path, ctx->args,
  162.                       NULL, NULL, 0, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)
  163.         == 0)
  164.     {
  165.         ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno,
  166.                       "CreateProcess(\"%s\") failed", ngx_argv[0]);

  167.         return 0;
  168.     }

  169.     ctx->child = pi.hProcess;

  170.     if (CloseHandle(pi.hThread) == 0) {
  171.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  172.                       "CloseHandle(pi.hThread) failed");
  173.     }

  174.     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
  175.                   "start %s process %P", ctx->name, pi.dwProcessId);

  176.     return pi.dwProcessId;
  177. }