nginx/src/os/unix/ngx_process.c
2004-02-03 16:43:54 +00:00

248 lines
6.6 KiB
C

#include <ngx_config.h>
#include <ngx_core.h>
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];
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle,
ngx_spawn_proc_pt proc, void *data,
char *name, ngx_int_t respawn)
{
sigset_t set, oset;
ngx_pid_t pid;
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, cycle->log, ngx_errno,
"sigprocmask() failed while spawning %s", name);
return NGX_ERROR;
}
}
switch (pid) {
case -1:
return NGX_ERROR;
case 0:
ngx_pid = ngx_getpid();
proc(cycle, data);
break;
default:
break;
}
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 pid;
}
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, cycle->log, ngx_errno,
"sigprocmask() failed while spawning %s", name);
return NGX_ERROR;
}
return pid;
}
ngx_pid_t ngx_exec(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
{
return ngx_spawn_process(cycle, ngx_exec_proc, ctx, ctx->name,
NGX_PROCESS_DETACHED);
}
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);
}
#if 0
void ngx_signal_processes(ngx_cycle_t *cycle)
{
ngx_uint_t i;
for (i = 0; i < ngx_last_process; i++) {
if (ngx_processes[i].signal0 == 0) {
continue;
}
#if 0
if (ngx_processes[i].exited) {
if (i != --ngx_last_process) {
ngx_processes[i--] = ngx_processes[ngx_last_process];
}
continue;
}
#endif
ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"kill (" PID_T_FMT ", %d)" ,
ngx_processes[i].pid, ngx_processes[i].signal0);
if (kill(ngx_processes[i].pid, ngx_processes[i].signal0) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"kill(%d, %d) failed",
ngx_processes[i].pid, ngx_processes[i].signal0);
continue;
}
if (ngx_processes[i].signal0 != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
ngx_processes[i].exiting = 1;
}
}
}
#endif
void ngx_respawn_processes(ngx_cycle_t *cycle)
{
ngx_uint_t i;
for (i = 0; i < ngx_last_process; i++) {
if (ngx_processes[i].exiting || !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);
}
}
}
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 ( ;; ) {
pid = waitpid(-1, &status, WNOHANG);
if (pid == 0) {
return;
}
if (pid == -1) {
err = ngx_errno;
if (err == NGX_EINTR) {
continue;
}
if (err == NGX_ECHILD && one) {
return;
}
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno,
"waitpid() failed");
return;
}
one = 1;
process = "";
for (i = 0; i < ngx_last_process; i++) {
if (ngx_processes[i].pid == pid) {
ngx_processes[i].status = status;
ngx_processes[i].exited = 1;
process = ngx_processes[i].name;
break;
}
}
if (i == ngx_last_process) {
process = "unknown process";
}
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));
}
if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
"%s " PID_T_FMT
" exited with fatal code %d and could not respawn",
process, pid, WEXITSTATUS(status));
ngx_processes[i].respawn = 0;
}
}
}