staticvoidngx_signal_handler(intsigno,siginfo_t*siginfo,void*ucontext){char*action;ngx_int_tignore;ngx_err_terr;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){caseNGX_PROCESS_MASTER:caseNGX_PROCESS_SINGLE:switch(signo){casengx_signal_value(NGX_SHUTDOWN_SIGNAL):ngx_quit=1;action=", shutting down";break;casengx_signal_value(NGX_TERMINATE_SIGNAL):caseSIGINT:ngx_terminate=1;action=", exiting";break;casengx_signal_value(NGX_NOACCEPT_SIGNAL):if(ngx_daemonized){ngx_noaccept=1;action=", stop accepting connections";}break;casengx_signal_value(NGX_RECONFIGURE_SIGNAL):ngx_reconfigure=1;action=", reconfiguring";break;casengx_signal_value(NGX_REOPEN_SIGNAL):ngx_reopen=1;action=", reopening logs";break;casengx_signal_value(NGX_CHANGEBIN_SIGNAL):if(ngx_getppid()==ngx_parent||ngx_new_binary>0){/* * Ignore the signal in the new binary if its parent is * not changed, 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;caseSIGALRM:ngx_sigalrm=1;break;caseSIGIO:ngx_sigio=1;break;caseSIGCHLD:ngx_reap=1;break;}break;caseNGX_PROCESS_WORKER:caseNGX_PROCESS_HELPER:switch(signo){casengx_signal_value(NGX_NOACCEPT_SIGNAL):if(!ngx_daemonized){break;}ngx_debug_quit=1;/* fall through */casengx_signal_value(NGX_SHUTDOWN_SIGNAL):ngx_quit=1;action=", shutting down";break;casengx_signal_value(NGX_TERMINATE_SIGNAL):caseSIGINT:ngx_terminate=1;action=", exiting";break;casengx_signal_value(NGX_REOPEN_SIGNAL):ngx_reopen=1;action=", reopening logs";break;casengx_signal_value(NGX_RECONFIGURE_SIGNAL):casengx_signal_value(NGX_CHANGEBIN_SIGNAL):caseSIGIO:action=", ignoring";break;}break;}if(siginfo&&siginfo->si_pid){ngx_log_error(NGX_LOG_NOTICE,ngx_cycle->log,0,"signal %d (%s) received from %P%s",signo,sig->signame,siginfo->si_pid,action);}else{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);}
casengx_signal_value(NGX_CHANGEBIN_SIGNAL):if(ngx_getppid()==ngx_parent||ngx_new_binary>0){/* * Ignore the signal in the new binary if its parent is * not changed, 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;
caseNGX_PROCESS_WORKER:caseNGX_PROCESS_HELPER:switch(signo){casengx_signal_value(NGX_NOACCEPT_SIGNAL):if(!ngx_daemonized){break;}ngx_debug_quit=1;/* fall through */casengx_signal_value(NGX_SHUTDOWN_SIGNAL):ngx_quit=1;action=", shutting down";break;
#1 if (!ngx_daemonized): 若非守护模式,直接 break 跳出内层 switch,即忽略该信号。 #2 ngx_debug_quit = 1;: 设置调试退出标志(特定场景下用于协调退出过程)。 #3 /* fall through */:注释表明这是有意穿透到下一个 case 标签,不加 break。 #4 紧接着是 case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):, 所以收到 SIGWINCH 的工作进程会执行与收到 SIGQUIT 完全相同的操作: ngx_quit = 1; 和 action = ", shutting down";。 意义: 对于工作进程,SIGWINCH 不仅停止接受新连接,还会优雅退出。 这与主进程仅停止接受连接而不退出的语义不同,因为工作进程退出后可由主进程重新拉起。
if(siginfo&&siginfo->si_pid){ngx_log_error(NGX_LOG_NOTICE,ngx_cycle->log,0,"signal %d (%s) received from %P%s",signo,sig->signame,siginfo->si_pid,action);}else{ngx_log_error(NGX_LOG_NOTICE,ngx_cycle->log,0,"signal %d (%s) received%s",signo,sig->signame,action);}
7 热升级信号 ignore
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");}