2003-11-20 00:26:41 +08:00
|
|
|
|
2004-09-28 16:34:51 +08:00
|
|
|
/*
|
2004-09-30 00:00:49 +08:00
|
|
|
* Copyright (C) Igor Sysoev
|
2004-09-28 16:34:51 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2003-11-20 00:26:41 +08:00
|
|
|
#include <ngx_config.h>
|
|
|
|
#include <ngx_core.h>
|
2004-04-05 04:32:09 +08:00
|
|
|
#include <ngx_event.h>
|
2004-07-15 00:01:42 +08:00
|
|
|
#include <ngx_channel.h>
|
2003-11-20 00:26:41 +08:00
|
|
|
|
|
|
|
|
2005-09-07 00:09:32 +08:00
|
|
|
typedef struct {
|
|
|
|
int signo;
|
|
|
|
char *signame;
|
|
|
|
void (*handler)(int signo);
|
|
|
|
} ngx_signal_t;
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-05 00:34:23 +08:00
|
|
|
static void ngx_execute_proc(ngx_cycle_t *cycle, void *data);
|
2005-09-07 00:09:32 +08:00
|
|
|
static void ngx_signal_handler(int signo);
|
|
|
|
static void ngx_process_get_status(void);
|
2004-01-06 04:55:48 +08:00
|
|
|
|
2004-10-11 23:07:03 +08:00
|
|
|
|
|
|
|
int ngx_argc;
|
|
|
|
char **ngx_argv;
|
|
|
|
char **ngx_os_argv;
|
|
|
|
|
|
|
|
ngx_int_t ngx_process_slot;
|
|
|
|
ngx_socket_t ngx_channel;
|
|
|
|
ngx_int_t ngx_last_process;
|
|
|
|
ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
|
2003-11-20 00:26:41 +08:00
|
|
|
|
|
|
|
|
2005-09-07 00:09:32 +08:00
|
|
|
ngx_signal_t signals[] = {
|
|
|
|
{ ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
|
|
|
|
"SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
|
|
|
|
ngx_signal_handler },
|
|
|
|
|
|
|
|
{ ngx_signal_value(NGX_REOPEN_SIGNAL),
|
|
|
|
"SIG" ngx_value(NGX_REOPEN_SIGNAL),
|
|
|
|
ngx_signal_handler },
|
|
|
|
|
|
|
|
{ ngx_signal_value(NGX_NOACCEPT_SIGNAL),
|
|
|
|
"SIG" ngx_value(NGX_NOACCEPT_SIGNAL),
|
|
|
|
ngx_signal_handler },
|
|
|
|
|
|
|
|
{ ngx_signal_value(NGX_TERMINATE_SIGNAL),
|
|
|
|
"SIG" ngx_value(NGX_TERMINATE_SIGNAL),
|
|
|
|
ngx_signal_handler },
|
|
|
|
|
|
|
|
{ ngx_signal_value(NGX_SHUTDOWN_SIGNAL),
|
|
|
|
"SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),
|
|
|
|
ngx_signal_handler },
|
|
|
|
|
|
|
|
{ ngx_signal_value(NGX_CHANGEBIN_SIGNAL),
|
|
|
|
"SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),
|
|
|
|
ngx_signal_handler },
|
|
|
|
|
|
|
|
{ SIGALRM, "SIGALRM", ngx_signal_handler },
|
|
|
|
|
|
|
|
{ SIGINT, "SIGINT", ngx_signal_handler },
|
|
|
|
|
|
|
|
{ SIGIO, "SIGIO", ngx_signal_handler },
|
|
|
|
|
|
|
|
{ SIGCHLD, "SIGCHLD", ngx_signal_handler },
|
|
|
|
|
|
|
|
{ SIGPIPE, "SIGPIPE, SIG_IGN", SIG_IGN },
|
|
|
|
|
|
|
|
{ 0, NULL, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-05-19 21:25:22 +08:00
|
|
|
ngx_pid_t
|
|
|
|
ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
|
|
|
|
char *name, ngx_int_t respawn)
|
2003-11-20 00:26:41 +08:00
|
|
|
{
|
2004-06-15 15:55:11 +08:00
|
|
|
u_long on;
|
2004-01-06 04:55:48 +08:00
|
|
|
ngx_pid_t pid;
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_int_t s;
|
2003-11-20 00:26:41 +08:00
|
|
|
|
2004-07-14 01:59:12 +08:00
|
|
|
if (respawn >= 0) {
|
|
|
|
s = respawn;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
for (s = 0; s < ngx_last_process; s++) {
|
|
|
|
if (ngx_processes[s].pid == -1) {
|
|
|
|
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);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-07-14 01:59:12 +08:00
|
|
|
}
|
|
|
|
}
|
2004-06-15 15:55:11 +08:00
|
|
|
|
|
|
|
|
2004-06-23 13:54:27 +08:00
|
|
|
if (respawn != NGX_PROCESS_DETACHED) {
|
2003-11-20 00:26:41 +08:00
|
|
|
|
2004-06-23 13:54:27 +08:00
|
|
|
/* Solaris 9 still has no AF_LOCAL */
|
2004-01-06 04:55:48 +08:00
|
|
|
|
2004-06-23 13:54:27 +08:00
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
|
|
|
|
{
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
"socketpair() failed while spawning \"%s\"", name);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-06-23 13:54:27 +08:00
|
|
|
}
|
2004-06-19 00:22:16 +08:00
|
|
|
|
2004-07-15 00:01:42 +08:00
|
|
|
ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
|
|
|
|
"channel %d:%d",
|
|
|
|
ngx_processes[s].channel[0],
|
|
|
|
ngx_processes[s].channel[1]);
|
|
|
|
|
2004-06-23 13:54:27 +08:00
|
|
|
if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
ngx_nonblocking_n " failed while spawning \"%s\"",
|
|
|
|
name);
|
|
|
|
ngx_close_channel(ngx_processes[s].channel, cycle->log);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-06-23 13:54:27 +08:00
|
|
|
}
|
2004-06-19 00:22:16 +08:00
|
|
|
|
2004-06-23 13:54:27 +08:00
|
|
|
if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
ngx_nonblocking_n " failed while spawning \"%s\"",
|
|
|
|
name);
|
|
|
|
ngx_close_channel(ngx_processes[s].channel, cycle->log);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-06-23 13:54:27 +08:00
|
|
|
}
|
2004-06-15 15:55:11 +08:00
|
|
|
|
2004-06-23 13:54:27 +08:00
|
|
|
on = 1;
|
|
|
|
if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
"ioctl(FIOASYNC) failed while spawning \"%s\"", name);
|
|
|
|
ngx_close_channel(ngx_processes[s].channel, cycle->log);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-06-23 13:54:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
"fcntl(F_SETOWN) failed while spawning \"%s\"", name);
|
|
|
|
ngx_close_channel(ngx_processes[s].channel, cycle->log);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-06-23 13:54:27 +08:00
|
|
|
}
|
|
|
|
|
2004-06-23 23:18:17 +08:00
|
|
|
if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
"fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
|
|
|
|
name);
|
|
|
|
ngx_close_channel(ngx_processes[s].channel, cycle->log);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-06-23 23:18:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
"fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
|
|
|
|
name);
|
|
|
|
ngx_close_channel(ngx_processes[s].channel, cycle->log);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2004-06-23 23:18:17 +08:00
|
|
|
}
|
|
|
|
|
2004-06-23 13:54:27 +08:00
|
|
|
ngx_channel = ngx_processes[s].channel[1];
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ngx_processes[s].channel[0] = -1;
|
|
|
|
ngx_processes[s].channel[1] = -1;
|
2004-06-15 15:55:11 +08:00
|
|
|
}
|
|
|
|
|
2004-06-19 00:22:16 +08:00
|
|
|
ngx_process_slot = s;
|
2004-06-15 15:55:11 +08:00
|
|
|
|
|
|
|
|
|
|
|
pid = fork();
|
|
|
|
|
2003-11-20 00:26:41 +08:00
|
|
|
switch (pid) {
|
2004-06-15 15:55:11 +08:00
|
|
|
|
2003-11-20 00:26:41 +08:00
|
|
|
case -1:
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
|
|
|
"fork() failed while spawning \"%s\"", name);
|
2004-06-23 13:54:27 +08:00
|
|
|
ngx_close_channel(ngx_processes[s].channel, cycle->log);
|
2005-09-23 19:02:22 +08:00
|
|
|
return NGX_INVALID_PID;
|
2003-11-20 00:26:41 +08:00
|
|
|
|
|
|
|
case 0:
|
2004-02-04 00:43:54 +08:00
|
|
|
ngx_pid = ngx_getpid();
|
2004-01-06 04:55:48 +08:00
|
|
|
proc(cycle, data);
|
2003-11-20 00:26:41 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-11-26 04:44:56 +08:00
|
|
|
break;
|
2003-11-20 00:26:41 +08:00
|
|
|
}
|
|
|
|
|
2004-12-21 20:30:30 +08:00
|
|
|
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);
|
2003-11-20 00:26:41 +08:00
|
|
|
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_processes[s].pid = pid;
|
|
|
|
ngx_processes[s].exited = 0;
|
|
|
|
|
2004-01-06 04:55:48 +08:00
|
|
|
if (respawn >= 0) {
|
2004-01-14 00:43:23 +08:00
|
|
|
return pid;
|
2004-01-06 04:55:48 +08:00
|
|
|
}
|
|
|
|
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_processes[s].proc = proc;
|
|
|
|
ngx_processes[s].data = data;
|
|
|
|
ngx_processes[s].name = name;
|
|
|
|
ngx_processes[s].exiting = 0;
|
2004-04-16 13:14:16 +08:00
|
|
|
|
|
|
|
switch (respawn) {
|
|
|
|
|
|
|
|
case NGX_PROCESS_RESPAWN:
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_processes[s].respawn = 1;
|
|
|
|
ngx_processes[s].just_respawn = 0;
|
|
|
|
ngx_processes[s].detached = 0;
|
2004-04-16 13:14:16 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NGX_PROCESS_JUST_RESPAWN:
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_processes[s].respawn = 1;
|
|
|
|
ngx_processes[s].just_respawn = 1;
|
|
|
|
ngx_processes[s].detached = 0;
|
2004-04-16 13:14:16 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NGX_PROCESS_DETACHED:
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_processes[s].respawn = 0;
|
|
|
|
ngx_processes[s].just_respawn = 0;
|
|
|
|
ngx_processes[s].detached = 1;
|
2004-04-16 13:14:16 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-07-14 01:59:12 +08:00
|
|
|
if (s == ngx_last_process) {
|
|
|
|
ngx_last_process++;
|
|
|
|
}
|
2003-11-20 00:26:41 +08:00
|
|
|
|
2004-01-14 00:43:23 +08:00
|
|
|
return pid;
|
2003-11-20 00:26:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-19 21:25:22 +08:00
|
|
|
ngx_pid_t
|
|
|
|
ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
|
2004-01-06 04:55:48 +08:00
|
|
|
{
|
2004-03-05 00:34:23 +08:00
|
|
|
return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name,
|
2004-01-14 05:33:59 +08:00
|
|
|
NGX_PROCESS_DETACHED);
|
2004-01-06 04:55:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-19 21:25:22 +08:00
|
|
|
static void
|
|
|
|
ngx_execute_proc(ngx_cycle_t *cycle, void *data)
|
2004-01-06 04:55:48 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-07 00:09:32 +08:00
|
|
|
ngx_int_t
|
|
|
|
ngx_init_signals(ngx_log_t *log)
|
|
|
|
{
|
|
|
|
ngx_signal_t *sig;
|
|
|
|
struct sigaction sa;
|
|
|
|
|
|
|
|
for (sig = signals; sig->signo != 0; sig++) {
|
|
|
|
ngx_memzero(&sa, sizeof(struct sigaction));
|
|
|
|
sa.sa_handler = sig->handler;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
if (sigaction(sig->signo, &sa, NULL) == -1) {
|
|
|
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
|
|
|
"sigaction(%s) failed", sig->signame);
|
|
|
|
return NGX_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NGX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-19 21:25:22 +08:00
|
|
|
void
|
2005-09-07 00:09:32 +08:00
|
|
|
ngx_signal_handler(int signo)
|
|
|
|
{
|
|
|
|
char *action;
|
|
|
|
ngx_int_t ignore;
|
|
|
|
ngx_err_t err;
|
|
|
|
ngx_signal_t *sig;
|
|
|
|
|
|
|
|
ignore = 0;
|
|
|
|
|
|
|
|
err = ngx_errno;
|
|
|
|
|
|
|
|
for (sig = signals; sig->signo != 0; sig++) {
|
|
|
|
if (sig->signo == signo) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-19 20:33:58 +08:00
|
|
|
ngx_time_update(0, 0);
|
2005-09-07 00:09:32 +08:00
|
|
|
|
|
|
|
action = "";
|
|
|
|
|
|
|
|
switch (ngx_process) {
|
|
|
|
|
|
|
|
case NGX_PROCESS_MASTER:
|
|
|
|
case NGX_PROCESS_SINGLE:
|
|
|
|
switch (signo) {
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
|
|
|
|
ngx_quit = 1;
|
|
|
|
action = ", shutting down";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_TERMINATE_SIGNAL):
|
|
|
|
case SIGINT:
|
|
|
|
ngx_terminate = 1;
|
|
|
|
action = ", exiting";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
|
|
|
|
ngx_noaccept = 1;
|
|
|
|
action = ", stop accepting connections";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
|
|
|
|
ngx_reconfigure = 1;
|
|
|
|
action = ", reconfiguring";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_REOPEN_SIGNAL):
|
|
|
|
ngx_reopen = 1;
|
|
|
|
action = ", reopening logs";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
|
|
|
|
if (getppid() > 1 || ngx_new_binary > 0) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ignore the signal in the new binary if its parent is
|
|
|
|
* not the init process, i.e. the old binary's process
|
|
|
|
* is still running. Or ingore the signal in the old binary's
|
|
|
|
* process if the new binary's process is already running.
|
|
|
|
*/
|
|
|
|
|
|
|
|
action = ", ignoring";
|
|
|
|
ignore = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ngx_change_binary = 1;
|
|
|
|
action = ", changing binary";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGALRM:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGIO:
|
|
|
|
ngx_sigio = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGCHLD:
|
|
|
|
ngx_reap = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NGX_PROCESS_WORKER:
|
|
|
|
switch (signo) {
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
|
|
|
|
ngx_debug_quit = 1;
|
|
|
|
case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
|
|
|
|
ngx_quit = 1;
|
|
|
|
action = ", shutting down";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_TERMINATE_SIGNAL):
|
|
|
|
case SIGINT:
|
|
|
|
ngx_terminate = 1;
|
|
|
|
action = ", exiting";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_REOPEN_SIGNAL):
|
|
|
|
ngx_reopen = 1;
|
|
|
|
action = ", reopening logs";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
|
|
|
|
case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
|
|
|
|
case SIGIO:
|
|
|
|
action = ", ignoring";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
|
|
|
|
"signal %d (%s) received%s", signo, sig->signame, action);
|
|
|
|
|
|
|
|
if (ignore) {
|
|
|
|
ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0,
|
|
|
|
"the changing binary signal is ignored: "
|
|
|
|
"you should shutdown or terminate "
|
|
|
|
"before either old or new binary's process");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (signo == SIGCHLD) {
|
|
|
|
ngx_process_get_status();
|
|
|
|
}
|
|
|
|
|
|
|
|
ngx_set_errno(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2005-05-19 21:25:22 +08:00
|
|
|
ngx_process_get_status(void)
|
2004-01-06 04:55:48 +08:00
|
|
|
{
|
|
|
|
int status;
|
|
|
|
char *process;
|
|
|
|
ngx_pid_t pid;
|
|
|
|
ngx_err_t err;
|
2004-06-15 15:55:11 +08:00
|
|
|
ngx_int_t i;
|
|
|
|
ngx_uint_t one;
|
2004-12-21 20:30:30 +08:00
|
|
|
|
2003-11-20 00:26:41 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-10-21 23:34:38 +08:00
|
|
|
#if (NGX_SOLARIS)
|
2004-10-11 23:07:03 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Solaris always calls the signal handler for each exited process
|
|
|
|
* despite waitpid() may be already called for this process
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (err == NGX_ECHILD) {
|
|
|
|
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, errno,
|
|
|
|
"waitpid() failed");
|
2005-10-19 20:33:58 +08:00
|
|
|
return;
|
2004-10-11 23:07:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2003-11-20 00:26:41 +08:00
|
|
|
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno,
|
|
|
|
"waitpid() failed");
|
2004-10-11 23:07:03 +08:00
|
|
|
|
2003-11-20 00:26:41 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-04-05 04:32:09 +08:00
|
|
|
|
|
|
|
if (ngx_accept_mutex_ptr) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* unlock the accept mutex if the abnormally exited process
|
|
|
|
* held it
|
|
|
|
*/
|
|
|
|
|
|
|
|
ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-20 00:26:41 +08:00
|
|
|
one = 1;
|
2004-07-14 01:59:12 +08:00
|
|
|
process = "unknown process";
|
2003-11-20 00:26:41 +08:00
|
|
|
|
2004-01-06 04:55:48 +08:00
|
|
|
for (i = 0; i < ngx_last_process; i++) {
|
|
|
|
if (ngx_processes[i].pid == pid) {
|
|
|
|
ngx_processes[i].status = status;
|
2004-01-09 05:02:06 +08:00
|
|
|
ngx_processes[i].exited = 1;
|
2004-01-06 04:55:48 +08:00
|
|
|
process = ngx_processes[i].name;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WTERMSIG(status)) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
|
2004-11-11 22:07:14 +08:00
|
|
|
"%s %P exited on signal %d%s",
|
2004-01-06 04:55:48 +08:00
|
|
|
process, pid, WTERMSIG(status),
|
|
|
|
WCOREDUMP(status) ? " (core dumped)" : "");
|
|
|
|
|
|
|
|
} else {
|
2004-12-21 20:30:30 +08:00
|
|
|
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
|
2004-11-11 22:07:14 +08:00
|
|
|
"%s %P exited with code %d",
|
2004-01-06 04:55:48 +08:00
|
|
|
process, pid, WEXITSTATUS(status));
|
|
|
|
}
|
2004-01-21 04:40:08 +08:00
|
|
|
|
|
|
|
if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) {
|
|
|
|
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
|
2004-11-11 22:07:14 +08:00
|
|
|
"%s %P exited with fatal code %d and could not respawn",
|
|
|
|
process, pid, WEXITSTATUS(status));
|
2004-01-21 04:40:08 +08:00
|
|
|
ngx_processes[i].respawn = 0;
|
|
|
|
}
|
2003-11-20 00:26:41 +08:00
|
|
|
}
|
|
|
|
}
|
2004-11-11 22:07:14 +08:00
|
|
|
|
|
|
|
|
2005-05-19 21:25:22 +08:00
|
|
|
void
|
|
|
|
ngx_debug_point(void)
|
2004-11-11 22:07:14 +08:00
|
|
|
{
|
|
|
|
ngx_core_conf_t *ccf;
|
|
|
|
|
|
|
|
ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
|
|
|
|
ngx_core_module);
|
|
|
|
|
|
|
|
switch (ccf->debug_points) {
|
|
|
|
|
|
|
|
case NGX_DEBUG_POINTS_STOP:
|
|
|
|
raise(SIGSTOP);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NGX_DEBUG_POINTS_ABORT:
|
2005-10-19 20:33:58 +08:00
|
|
|
ngx_abort();
|
2004-11-11 22:07:14 +08:00
|
|
|
}
|
|
|
|
}
|