diff src/os/win32/ngx_process.c @ 2725:d43d73277c5c

Win32 master/workers model
author Igor Sysoev <igor@sysoev.ru>
date Mon, 20 Apr 2009 06:08:47 +0000
parents 23fb87bddda1
children d52cf82d0d77
line wrap: on
line diff
--- a/src/os/win32/ngx_process.c
+++ b/src/os/win32/ngx_process.c
@@ -8,12 +8,212 @@
 #include <ngx_core.h>
 
 
-int            ngx_argc;
-char         **ngx_argv;
-char         **ngx_os_argv;
+int              ngx_argc;
+char           **ngx_argv;
+char           **ngx_os_argv;
+
+ngx_int_t        ngx_last_process;
+ngx_process_t    ngx_processes[NGX_MAX_PROCESSES];
 
 
-ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
+ngx_pid_t
+ngx_spawn_process(ngx_cycle_t *cycle, char *name, ngx_int_t respawn)
 {
-    return /* STUB */ 0;
+    u_long          rc, n;
+    ngx_int_t       s;
+    ngx_pid_t       pid;
+    ngx_exec_ctx_t  ctx;
+    char            file[MAX_PATH + 1];
+
+    if (respawn >= 0) {
+        s = respawn;
+
+    } else {
+        for (s = 0; s < ngx_last_process; s++) {
+            if (ngx_processes[s].handle == NULL) {
+                break;
+            }
+        }
+
+        if (s == NGX_MAX_PROCESSES) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                          "no more than %d processes can be spawned",
+                          NGX_MAX_PROCESSES);
+            return NGX_INVALID_PID;
+        }
+    }
+
+    n = GetModuleFileName(NULL, file, MAX_PATH);
+
+    if (n == 0) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "GetModuleFileName() failed");
+        return NGX_INVALID_PID;
+    }
+
+    file[n] = '\0';
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+                   "GetModuleFileName: \"%s\"", file);
+
+    ctx.path = file;
+    ctx.name = name;
+    ctx.argv = NULL;
+    ctx.envp = NULL;
+
+    pid = ngx_execute(cycle, &ctx);
+
+    if (pid == NGX_INVALID_PID) {
+        return pid;
+    }
+
+    ngx_memzero(&ngx_processes[s], sizeof(ngx_process_t));
+
+    ngx_processes[s].handle = ctx.child;
+    ngx_processes[s].pid = pid;
+    ngx_processes[s].name = name;
+
+    ngx_sprintf(ngx_processes[s].term_event, "ngx_%s_term_%ul%Z", name, pid);
+    ngx_sprintf(ngx_processes[s].quit_event, "ngx_%s_quit_%ul%Z", name, pid);
+    ngx_sprintf(ngx_processes[s].reopen_event, "ngx_%s_reopen_%ul%Z",
+                name, pid);
+
+    rc = WaitForSingleObject(ngx_master_process_event, 5000);
+
+    ngx_time_update(0, 0);
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+                   "WaitForSingleObject: %ul", rc);
+
+    switch (rc) {
+
+    case WAIT_OBJECT_0:
+
+        ngx_processes[s].term = OpenEvent(EVENT_MODIFY_STATE, 0,
+                                          (char *) ngx_processes[s].term_event);
+        if (ngx_processes[s].term == NULL) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "OpenEvent(\"%s\") failed",
+                          ngx_processes[s].term_event);
+            goto failed;
+        }
+
+        ngx_processes[s].quit = OpenEvent(EVENT_MODIFY_STATE, 0,
+                                          (char *) ngx_processes[s].quit_event);
+        if (ngx_processes[s].quit == NULL) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "OpenEvent(\"%s\") failed",
+                          ngx_processes[s].quit_event);
+            goto failed;
+        }
+
+        ngx_processes[s].reopen = OpenEvent(EVENT_MODIFY_STATE, 0,
+                                       (char *) ngx_processes[s].reopen_event);
+        if (ngx_processes[s].reopen == NULL) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "OpenEvent(\"%s\") failed",
+                          ngx_processes[s].reopen_event);
+            goto failed;
+        }
+
+        if (ResetEvent(ngx_master_process_event) == 0) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                          "ResetEvent(\"%s\") failed",
+                          ngx_master_process_event_name);
+            goto failed;
+        }
+
+        break;
+ 
+    case WAIT_TIMEOUT:
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                      "the event \"%s\" was not signaled for 5s",
+                      ngx_master_process_event_name);
+        goto failed;
+
+    case WAIT_FAILED:
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "WaitForSingleObject(\"%s\") failed",
+                      ngx_master_process_event_name);
+
+        goto failed;
+    }
+
+    if (respawn >= 0) {
+        return pid;
+    }
+
+    switch (respawn) {
+
+    case NGX_PROCESS_RESPAWN:
+        ngx_processes[s].just_respawn = 0;
+        break;
+
+    case NGX_PROCESS_JUST_RESPAWN:
+        ngx_processes[s].just_respawn = 1;
+        break;
+    }
+
+    if (s == ngx_last_process) {
+        ngx_last_process++;
+    }
+
+    return pid;
+
+failed:
+
+    if (ngx_processes[s].reopen) {
+        ngx_close_handle(ngx_processes[s].reopen);
+    }
+
+    if (ngx_processes[s].quit) {
+        ngx_close_handle(ngx_processes[s].quit);
+    }
+
+    if (ngx_processes[s].term) {
+        ngx_close_handle(ngx_processes[s].term);
+    }
+
+    TerminateProcess(ngx_processes[s].handle, 2);
+
+    if (ngx_processes[s].handle) {
+        ngx_close_handle(ngx_processes[s].handle);
+    }
+
+    return NGX_INVALID_PID;
 }
+
+
+ngx_pid_t
+ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
+{
+    STARTUPINFO          si;
+    PROCESS_INFORMATION  pi;
+
+    ngx_memzero(&si, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+
+    ngx_memzero(&pi, sizeof(PROCESS_INFORMATION));
+
+    if (CreateProcess(ctx->path, /* STUB */ NULL,
+                      NULL, NULL, 0, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)
+        == 0)
+    {
+        ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno,
+                      "CreateProcess(\"%s\") failed", ngx_argv[0]);
+
+        return 0;
+    }
+
+    ctx->child = pi.hProcess;
+
+    if (CloseHandle(pi.hThread) == 0) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "CloseHandle(pi.hThread) failed");
+    }
+
+    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
+                  "start %s process %P", ctx->name, pi.dwProcessId);
+
+    return pi.dwProcessId;
+}