One Level Up
Top Level
src/os/unix/ngx_process.c - nginx-1.7.10
Global variables defined
Data types defined
Functions defined
Source code
- #include <ngx_config.h>
- #include <ngx_core.h>
- #include <ngx_event.h>
- #include <ngx_channel.h>
- typedef struct {
- int signo;
- char *signame;
- char *name;
- void (*handler)(int signo);
- } ngx_signal_t;
- static void ngx_execute_proc(ngx_cycle_t *cycle, void *data);
- static void ngx_signal_handler(int signo);
- static void ngx_process_get_status(void);
- static void ngx_unlock_mutexes(ngx_pid_t pid);
- 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];
- ngx_signal_t signals[] = {
- { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
- "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
- "reload",
- ngx_signal_handler },
- { ngx_signal_value(NGX_REOPEN_SIGNAL),
- "SIG" ngx_value(NGX_REOPEN_SIGNAL),
- "reopen",
- 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),
- "stop",
- ngx_signal_handler },
- { ngx_signal_value(NGX_SHUTDOWN_SIGNAL),
- "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),
- "quit",
- 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 },
- { SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN },
- { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN },
- { 0, NULL, "", NULL }
- };
- ngx_pid_t
- ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
- char *name, ngx_int_t respawn)
- {
- u_long on;
- ngx_pid_t pid;
- ngx_int_t s;
- 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);
- return NGX_INVALID_PID;
- }
- }
- if (respawn != NGX_PROCESS_DETACHED) {
-
- 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);
- return NGX_INVALID_PID;
- }
- ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
- "channel %d:%d",
- ngx_processes[s].channel[0],
- ngx_processes[s].channel[1]);
- 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);
- return NGX_INVALID_PID;
- }
- 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);
- return NGX_INVALID_PID;
- }
- 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);
- return NGX_INVALID_PID;
- }
- 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);
- return NGX_INVALID_PID;
- }
- 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);
- return NGX_INVALID_PID;
- }
- 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);
- return NGX_INVALID_PID;
- }
- ngx_channel = ngx_processes[s].channel[1];
- } else {
- ngx_processes[s].channel[0] = -1;
- ngx_processes[s].channel[1] = -1;
- }
- ngx_process_slot = s;
- pid = fork();
- switch (pid) {
- case -1:
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- "fork() failed while spawning \"%s\"", name);
- ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_INVALID_PID;
- case 0:
- ngx_pid = ngx_getpid();
- proc(cycle, data);
- break;
- default:
- break;
- }
- ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);
- ngx_processes[s].pid = pid;
- ngx_processes[s].exited = 0;
- if (respawn >= 0) {
- return pid;
- }
- ngx_processes[s].proc = proc;
- ngx_processes[s].data = data;
- ngx_processes[s].name = name;
- ngx_processes[s].exiting = 0;
- switch (respawn) {
- case NGX_PROCESS_NORESPAWN:
- ngx_processes[s].respawn = 0;
- ngx_processes[s].just_spawn = 0;
- ngx_processes[s].detached = 0;
- break;
- case NGX_PROCESS_JUST_SPAWN:
- ngx_processes[s].respawn = 0;
- ngx_processes[s].just_spawn = 1;
- ngx_processes[s].detached = 0;
- break;
- case NGX_PROCESS_RESPAWN:
- ngx_processes[s].respawn = 1;
- ngx_processes[s].just_spawn = 0;
- ngx_processes[s].detached = 0;
- break;
- case NGX_PROCESS_JUST_RESPAWN:
- ngx_processes[s].respawn = 1;
- ngx_processes[s].just_spawn = 1;
- ngx_processes[s].detached = 0;
- break;
- case NGX_PROCESS_DETACHED:
- ngx_processes[s].respawn = 0;
- ngx_processes[s].just_spawn = 0;
- ngx_processes[s].detached = 1;
- break;
- }
- if (s == ngx_last_process) {
- ngx_last_process++;
- }
- return pid;
- }
- ngx_pid_t
- ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
- {
- return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name,
- NGX_PROCESS_DETACHED);
- }
- static void
- ngx_execute_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);
- }
- 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) {
- #if (NGX_VALGRIND)
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- "sigaction(%s) failed, ignored", sig->signame);
- #else
- ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
- "sigaction(%s) failed", sig->signame);
- return NGX_ERROR;
- #endif
- }
- }
- return NGX_OK;
- }
- void
- 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;
- }
- }
- ngx_time_sigsafe_update();
- 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):
- if (ngx_daemonized) {
- 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) {
-
- action = ", ignoring";
- ignore = 1;
- break;
- }
- ngx_change_binary = 1;
- action = ", changing binary";
- break;
- case SIGALRM:
- ngx_sigalrm = 1;
- break;
- case SIGIO:
- ngx_sigio = 1;
- break;
- case SIGCHLD:
- ngx_reap = 1;
- break;
- }
- break;
- case NGX_PROCESS_WORKER:
- case NGX_PROCESS_HELPER:
- switch (signo) {
- case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
- if (!ngx_daemonized) {
- break;
- }
- 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
- ngx_process_get_status(void)
- {
- int status;
- char *process;
- ngx_pid_t pid;
- ngx_err_t err;
- ngx_int_t i;
- ngx_uint_t one;
- 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;
- }
-
- if (err == NGX_ECHILD) {
- ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, err,
- "waitpid() failed");
- return;
- }
- ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
- "waitpid() failed");
- return;
- }
- one = 1;
- process = "unknown 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 (WTERMSIG(status)) {
- #ifdef WCOREDUMP
- ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
- "%s %P exited on signal %d%s",
- process, pid, WTERMSIG(status),
- WCOREDUMP(status) ? " (core dumped)" : "");
- #else
- ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
- "%s %P exited on signal %d",
- process, pid, WTERMSIG(status));
- #endif
- } else {
- ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
- "%s %P 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 %P exited with fatal code %d "
- "and cannot be respawned",
- process, pid, WEXITSTATUS(status));
- ngx_processes[i].respawn = 0;
- }
- ngx_unlock_mutexes(pid);
- }
- }
- static void
- ngx_unlock_mutexes(ngx_pid_t pid)
- {
- ngx_uint_t i;
- ngx_shm_zone_t *shm_zone;
- ngx_list_part_t *part;
- ngx_slab_pool_t *sp;
-
- if (ngx_accept_mutex_ptr) {
- (void) ngx_shmtx_force_unlock(&ngx_accept_mutex, pid);
- }
-
- part = (ngx_list_part_t *) &ngx_cycle->shared_memory.part;
- shm_zone = part->elts;
- for (i = 0; ; i++) {
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
- part = part->next;
- shm_zone = part->elts;
- i = 0;
- }
- sp = (ngx_slab_pool_t *) shm_zone[i].shm.addr;
- if (ngx_shmtx_force_unlock(&sp->mutex, pid)) {
- ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
- "shared memory zone \"%V\" was locked by %P",
- &shm_zone[i].shm.name, pid);
- }
- }
- }
- void
- ngx_debug_point(void)
- {
- 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:
- ngx_abort();
- }
- }
- ngx_int_t
- ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_int_t pid)
- {
- ngx_signal_t *sig;
- for (sig = signals; sig->signo != 0; sig++) {
- if (ngx_strcmp(name, sig->name) == 0) {
- if (kill(pid, sig->signo) != -1) {
- return 0;
- }
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- "kill(%P, %d) failed", pid, sig->signo);
- }
- }
- return 1;
- }
One Level Up
Top Level