nginx signal 之 stop

        当运行的nginx程序收到了 stop信号后是如何处理,使整个程序停下来的呢? 总结了下,主要有下面几个步骤:

 

      一 master进程收到 stop 信号后,把 ngx_terminate 设置为1

 

      二 master看到ngx_terminate 为1 ,通过channel向子进程发送 NGX_CMD_TERMINATE 命令

 

      三 子进程收到命令后,把  ngx_terminate = 1

 

      四 子进程看到  ngx_terminate 为1 , 直接调用ngx_worker_process_exit 结束进程

 

      五 子进程结束的时候,会向master进程发送一个 SIGCHLD 信号

 

      六 master进程收到sigchild信号后,把ngx_reap =1 并调用 ngx_process_get_status 得到退出的进程并设置进程的状态。

 

      七 master看到ngx_reap 就调用 ngx_reap_children 回收子进程

 

      八 都所有的子进程都回收完毕,master就调用 ngx_master_process_exit 退出。

 

 

      下面对这些过程进行详细分析:

 

       一   ngx_process.c 中的ngx_signal_handler 函数

     //收到stop信号 case ngx_signal_value(NGX_TERMINATE_SIGNAL): case SIGINT: ngx_terminate = 1; action = ", exiting"; break;

 

 

     二  在ngx_process_cycle.c 中古 ngx_master_process_cycle函数中

  //收到stop信号 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_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; }

 

  上面的delay等待时间,每次都翻倍,直到1000的时候,就强制杀进程。

   sigio用户缓冲,防止频繁的向子进程发送信号。

 

  三 ngx_process_cycle.c中的 ngx_channel_handler函数,主要如下:

 

//读取master进程的命令 n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log); //设置value case NGX_CMD_TERMINATE: ngx_terminate = 1; break;

 

四  ngx_process_cycle.c 中的 ngx_worker_process_cycle函数中

 

//结束子进程 if (ngx_terminate) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); ngx_worker_process_exit(cycle); }

 

五  系统自动执行的

 

六  在ngx_process.c中的 ngx_signal_handler函数中

 

case SIGCHLD: ngx_reap = 1; //调用 if (signo == SIGCHLD) { ngx_process_get_status(); }

 

在ngx_process_get_status()函数中,很重要的一个操作就是把退出进程的exited 设置1

 

ngx_processes[i].exited = 1;

 

 

七  在ngx_process.c 中的ngx_master_process_cycle函数中

//回收子进程 if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); live = ngx_reap_children(cycle); }

 

在 ngx_reap_children中,

把 ngx_processes[i].exited 为1的进程进行回收。

 

存在退出中的进程 ,设置live为1

if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
            live = 1;
        }

这样表示子还有子进程没有退出。

 

八  ngx_process_cycle.c中的ngx_master_process_cycle函数中

//收到结束的信号并且所有worker进程都死了 if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); }

 

也就是需要所有worker进程都退出了,那么就退出master进程。

 

 

总结 : 整个过程通过channel 实现了父进程向子进程发送命令,子进程通过信号量向父进程报告自己的状态,整个过程非常清晰。

 

 

 

 

 

你可能感兴趣的:(nginx,cache,cmd,action,Signal,delay)