您的位置:首页 > 其它

NGX 信号处理流程

2013-07-11 10:25 162 查看
int ngx_cdecl
main(int argc, char *const *argv)
{
....
#if !(NGX_WIN32)

if (ngx_init_signals(cycle->log) != NGX_OK) { // 服务器启动时进行初始化信号处理
return 1;
}

if (!ngx_inherited && ccf->daemon) {
if (ngx_daemon(cycle->log) != NGX_OK) {
return 1;
}

ngx_daemonized = 1;
}

if (ngx_inherited) {
ngx_daemonized = 1;
}

#endif
......

// 单进程服务器
if (ngx_process == NGX_PROCESS_SINGLE) {
ngx_single_process_cycle(cycle);

} else {
ngx_master_process_cycle(cycle);
}

return 0;
}
下来再看看ngx_init_signals函数实现之前先看看结构
typedef struct {
    int     signo;       		// 信号值
    char   *signame;	// 信号名字
    char   *name;		// 服务器响应信号操作的名字
    void  (*handler)(int signo);// 信号处理函数
} ngx_signal_t;
再看看全局变量ngx_signal_t  signals[] 所有的信号及其处理函数
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_init_signals函数是将上面初始化的信号注册到系统中去
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;
//sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号搁置
        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;
}
下面看看重头函数ngx_signal_handler实现这里解释一个信号处理,其他类似
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_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:// 系统受到 SIGINT,系统调用此信号处理函数,设置全局变量ngx_terminate值置1 下面的分支类似            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) {                /*                 * 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:            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);}
这里处理完毕了吗,还没有以服务器模式为NGX_PROCESS_MASTER为例,ngx_master_process_cycle函数中
创建完工作进程和管理进程后,主进程进入循环,并停滞在
        // 等待信号唤醒        sigsuspend(&set);// 注意set是一个空信号集
进程收到信号并处理信号函数后,此函数返回,
程序进入下面执行ngx_terminate在信号处理函数中被置1
        if (ngx_terminate) {            if (delay == 0) {                delay = 50;            }            if (sigio) {                sigio--;                continue;            }            sigio = ccf->worker_processes + 2 /* cache processes */;            if (delay > 1000) {                ngx_signal_worker_processes(cycle, SIGKILL);            } else {
		// 向工作线程发送NGX_TERMINATE_SIGNAL信号                ngx_signal_worker_processes(cycle,                                       ngx_signal_value(NGX_TERMINATE_SIGNAL));            }            continue;        }
这就是信号处理流程,那么有一个问题,信号如何被发送的?

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: