aboutsummaryrefslogtreecommitdiffstats
path: root/app/nginx/src/os/win32/ngx_process.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/nginx/src/os/win32/ngx_process.c')
-rw-r--r--app/nginx/src/os/win32/ngx_process.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/app/nginx/src/os/win32/ngx_process.c b/app/nginx/src/os/win32/ngx_process.c
new file mode 100644
index 0000000..57b1ae9
--- /dev/null
+++ b/app/nginx/src/os/win32/ngx_process.c
@@ -0,0 +1,238 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+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_spawn_process(ngx_cycle_t *cycle, char *name, ngx_int_t respawn)
+{
+ u_long rc, n, code;
+ ngx_int_t s;
+ ngx_pid_t pid;
+ ngx_exec_ctx_t ctx;
+ HANDLE events[2];
+ 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.args = GetCommandLine();
+ 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_%P%Z", name, pid);
+ ngx_sprintf(ngx_processes[s].quit_event, "ngx_%s_quit_%P%Z", name, pid);
+ ngx_sprintf(ngx_processes[s].reopen_event, "ngx_%s_reopen_%P%Z",
+ name, pid);
+
+ events[0] = ngx_master_process_event;
+ events[1] = ctx.child;
+
+ rc = WaitForMultipleObjects(2, events, 0, 5000);
+
+ ngx_time_update();
+
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+ "WaitForMultipleObjects: %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_OBJECT_0 + 1:
+ if (GetExitCodeProcess(ctx.child, &code) == 0) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "GetExitCodeProcess(%P) failed", pid);
+ }
+
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+ "%s process %P exited with code %Xl",
+ name, pid, code);
+
+ goto failed;
+
+ 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_spawn = 0;
+ break;
+
+ case NGX_PROCESS_JUST_RESPAWN:
+ ngx_processes[s].just_spawn = 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);
+ ngx_processes[s].handle = NULL;
+ }
+
+ 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, ctx->args,
+ 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;
+}