nginx ngx_process 2



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 );
}


// execve 执行对应的exe文件


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 )
{
ngx_log_error( NGX_LOG_EMERG, log, ngx_errno,
"sigaction(%s) failed", sig->signame );


return NGX_ERROR;
}
}


return NGX_OK;
}


// 通用信号的处理函数, 更新全局变量的值,例如提醒woker进程和slave进程退出等


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_update( 0, 0 );


action = "";


// ngx_process  指定了当前是master  还是slave


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:
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):
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 ) // 是子进程退出的信号,则waitpid回收之
{
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;
}


// NGX_ECHILD ECHILD 错误表示  No children, 没有子进程,则直接返回


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;
}


// pid !=  -1 


if ( ngx_accept_mutex_ptr ) 
{


/*
* unlock the accept mutex if the abnormally exited process
* held it  如果有 ngx_accept_mutex_ptr,则设置为0
*/


ngx_atomic_cmp_set( ngx_accept_mutex_ptr, pid, 0 );
}




one = 1;
process = "unknown process";


// 在子进程数组中找到该pid,更新该pid的状态


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;
}
}


// WTERMSIG(status )  获得 使子进程终止的信号编号 


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));
}


/*


1,在程序中,用exit来设置进程的退出值时,虽然该函数的参数类型为int型,
但再父进程中只能取到其值的低8位.所以用exit返回值时,高于255的值是没有意义的. 
2,对于system函数,返回值是由两部分组成的,低8位值表示所执行的脚本在执行过程中所接收到的信号值,
其余的位表示的脚本exit退出时所设置的值, 
即脚本内exit退出是的值的低8位,在system返回值的低9-16位.


如果子进程退出值为2,则打印下日志


*/


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;
}
}
}




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();
}
}


//在signals数组中找到参数name对应的信号整数,向参数pid发信号


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;
}

你可能感兴趣的:(nginx ngx_process 2)