⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ngx_process.c

📁 nginx 反向代理0.7.1版本 用于实现反向代理
💻 C
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_event.h>#include <ngx_channel.h>typedef struct {     int     signo;     char   *signame;     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);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),      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 }};ngx_pid_tngx_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) {        /* Solaris 9 still has no AF_LOCAL */        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_RESPAWN:        ngx_processes[s].respawn = 1;        ngx_processes[s].just_respawn = 0;        ngx_processes[s].detached = 0;        break;    case NGX_PROCESS_JUST_RESPAWN:        ngx_processes[s].respawn = 1;        ngx_processes[s].just_respawn = 1;        ngx_processes[s].detached = 0;        break;    case NGX_PROCESS_DETACHED:        ngx_processes[s].respawn = 0;        ngx_processes[s].just_respawn = 0;        ngx_processes[s].detached = 1;        break;    }    if (s == ngx_last_process) {        ngx_last_process++;    }    return pid;}ngx_pid_tngx_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 voidngx_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_tngx_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;}voidngx_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_update(0, 0);    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 ignore 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 voidngx_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 (NGX_SOLARIS || NGX_FREEBSD)            /*             * Solaris always calls the signal handler for each exited process             * despite waitpid() may be already called for this process.             *             * When several processes exit at the same time FreeBSD may             * erroneously call the signal handler for 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");                return;            }#endif            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno,                          "waitpid() failed");            return;        }        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);        }        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)) {            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_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 can not be respawn",                          process, pid, WEXITSTATUS(status));            ngx_processes[i].respawn = 0;        }    }}voidngx_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();    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -