Mercurial > hg > nginx
diff src/os/unix/ngx_process.c @ 218:05592fd7a436
nginx-0.0.1-2004-01-05-23:55:48 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 05 Jan 2004 20:55:48 +0000 |
parents | 8dee38ea9117 |
children | f57597ec5249 |
line wrap: on
line diff
--- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -3,73 +3,241 @@ #include <ngx_core.h> -void testone(ngx_log_t *log) -{ - ngx_log_debug(log, "child process"); - ngx_msleep(5000); - exit(0); -} +static void ngx_exec_proc(ngx_cycle_t *cycle, void *data); + +ngx_uint_t ngx_last_process; +ngx_process_t ngx_processes[NGX_MAX_PROCESSES]; -int ngx_spawn_process(ngx_log_t *log) +ngx_int_t ngx_spawn_process(ngx_cycle_t *cycle, + ngx_spawn_proc_pt proc, void *data, + char *name, ngx_int_t respawn) { - pid_t pid; - sigset_t set, oset; + sigset_t set, oset; + ngx_pid_t pid; - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed"); + if (respawn < 0) { + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed while spawning %s", name); + return NGX_ERROR; + } } pid = fork(); + if (pid == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "fork() failed while spawning \"%s\"", name); + } + if (pid == -1 || pid == 0) { if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "sigprocmask() failed"); + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed while spawning %s", name); + return NGX_ERROR; } } switch (pid) { case -1: - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "fork() failed"); return NGX_ERROR; case 0: - testone(log); + proc(cycle, data); break; default: break; } -ngx_log_debug(log, "parent process, child: " PID_T_FMT _ pid); + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "spawn %s: " PID_T_FMT, name, pid); + + if (respawn >= 0) { + ngx_processes[respawn].pid = pid; + ngx_processes[respawn].exited = 0; + return NGX_OK; + } - /* book keeping */ + ngx_processes[ngx_last_process].pid = pid; + ngx_processes[ngx_last_process].proc = proc; + ngx_processes[ngx_last_process].data = data; + ngx_processes[ngx_last_process].name = name; + ngx_processes[ngx_last_process].respawn = + (respawn == NGX_PROCESS_RESPAWN) ? 1 : 0; + ngx_processes[ngx_last_process].detached = + (respawn == NGX_PROCESS_DETACHED) ? 1 : 0; + ngx_processes[ngx_last_process].exited = 0; + ngx_processes[ngx_last_process].exiting = 0; + ngx_last_process++; if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed"); + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed while spawning %s", name); + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_int_t ngx_exec(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx) +{ + if (ngx_spawn_process(cycle, ngx_exec_proc, ctx, ctx->name, + NGX_PROCESS_DETACHED) == NGX_ERROR) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "can not spawn %s", ctx->name); + return NGX_ERROR; } return NGX_OK; } +static void ngx_exec_proc(ngx_cycle_t *cycle, void *data) +{ + ngx_exec_ctx_t *ctx = data; + + if (execve(ctx->path, ctx->argv, ctx->envp) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "execve() failed while executing %s \"%s\"", + ctx->name, ctx->path); + } + + exit(1); +} + + +void ngx_signal_processes(ngx_cycle_t *cycle, ngx_int_t signal) +{ + sigset_t set, oset; + ngx_uint_t i; + + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed while signaling processes"); + return; + } + + for (i = 0; i < ngx_last_process; i++) { + + if (ngx_processes[i].detached) { + continue; + } + + if (ngx_processes[i].exited) { + if (i != --ngx_last_process) { + ngx_processes[i--] = ngx_processes[ngx_last_process]; + } + continue; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "kill (" PID_T_FMT ", %d)" , + ngx_processes[i].pid, signal); + + if (kill(ngx_processes[i].pid, signal) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "kill(%d, %d) failed", ngx_processes[i].pid, signal); + continue; + } + + if (signal != ngx_signal_value(NGX_REOPEN_SIGNAL)) { + ngx_processes[i].exiting = 1; + } + } + + if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed while signaling processes"); + } +} + + +void ngx_respawn_processes(ngx_cycle_t *cycle) +{ + sigset_t set, oset; + ngx_uint_t i; + + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed while respawning processes"); + return; + } + + /* + * to avoid a race condition we can check and set value of ngx_respawn + * only in signal handler or while SIGCHLD is blocked + */ + + if (ngx_respawn) { + + for (i = 0; i < ngx_last_process; i++) { + if (!ngx_processes[i].exited) { + continue; + } + + if (!ngx_processes[i].respawn) { + if (i != --ngx_last_process) { + ngx_processes[i--] = ngx_processes[ngx_last_process]; + } + continue; + } + + if (ngx_spawn_process(cycle, + ngx_processes[i].proc, ngx_processes[i].data, + ngx_processes[i].name, i) == NGX_ERROR) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "can not respawn %s", ngx_processes[i].name); + } + } + + ngx_respawn = 0; + } + + if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "sigprocmask() failed while respawning processes"); + } +} + + +#if 0 void ngx_sigchld_handler(int signo) { - int status, one; - pid_t pid; - ngx_err_t err; - struct timeval tv; + int status; + char *process; + ngx_pid_t pid; + ngx_err_t err; + ngx_uint_t i, one; + struct timeval tv; ngx_gettimeofday(&tv); + ngx_time_update(tv.tv_sec); - if (ngx_cached_time != tv.tv_sec) { - ngx_cached_time = tv.tv_sec; - ngx_time_update(); - } + ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, + "signal #%d (SIGCHLD) received", signo); +} +#endif + +void ngx_process_get_status() +{ + int status; + char *process; + ngx_pid_t pid; + ngx_err_t err; + ngx_uint_t i, one; + struct timeval tv; one = 0; for ( ;; ) { @@ -96,18 +264,39 @@ void ngx_sigchld_handler(int signo) } one = 1; + process = ""; - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "process " PID_T_FMT " exited with code %d", pid, status); + for (i = 0; i < ngx_last_process; i++) { + if (ngx_processes[i].pid == pid) { + ngx_processes[i].status = status; - /* TODO: restart handler */ + if (!ngx_processes[i].exiting) { + ngx_processes[i].exited = 1; + + if (ngx_processes[i].respawn) { + ngx_respawn = 1; + } + } -#if 0 - ngx_msleep(2000); -#endif + process = ngx_processes[i].name; + break; + } + } + + if (i == ngx_last_process) { + process = "unknown process"; + } -#if 0 - ngx_spawn_process(ngx_cycle->log); -#endif + if (WTERMSIG(status)) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "%s " PID_T_FMT " exited on signal %d%s", + process, pid, WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + + } else { + ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, + "%s " PID_T_FMT " exited with code %d", + process, pid, WEXITSTATUS(status)); + } } }