diff options
Diffstat (limited to 'app/nginx/src/os/win32/ngx_process.c')
-rw-r--r-- | app/nginx/src/os/win32/ngx_process.c | 238 |
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; +} |