ngx_process_get_status

张开发
2026/4/18 0:51:19 15 分钟阅读

分享文章

ngx_process_get_status
1 定义ngx_process_get_status 函数 定义在 ./nginx-1.24.0/src/os/unix/ngx_process.cstaticvoidngx_process_get_status(void){intstatus;char*process;ngx_pid_tpid;ngx_err_terr;ngx_int_ti;ngx_uint_tone;one0;for(;;){pidwaitpid(-1,status,WNOHANG);if(pid0){return;}if(pid-1){errngx_errno;if(errNGX_EINTR){continue;}if(errNGX_ECHILDone){return;}/* * 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(errNGX_ECHILD){ngx_log_error(NGX_LOG_INFO,ngx_cycle-log,err,waitpid() failed);return;}ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,err,waitpid() failed);return;}one1;processunknown process;for(i0;ingx_last_process;i){if(ngx_processes[i].pidpid){ngx_processes[i].statusstatus;ngx_processes[i].exited1;processngx_processes[i].name;break;}}if(WTERMSIG(status)){#ifdefWCOREDUMPngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,%s %P exited on signal %d%s,process,pid,WTERMSIG(status),WCOREDUMP(status)? (core dumped):);#elsengx_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));}if(WEXITSTATUS(status)2ngx_processes[i].respawn){ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,%s %P exited with fatal code %d and cannot be respawned,process,pid,WEXITSTATUS(status));ngx_processes[i].respawn0;}ngx_unlock_mutexes(pid);}}ngx_process_get_status 函数是 它是 Nginx 处理子进程退出状态的核心函数 通常作为 SIGCHLD 信号的处理函数被调用2 详解1 函数签名staticvoidngx_process_get_status(void)无参数和返回值2 逻辑流程1 局部变量 2 循环 回收子进程 3 更新进程管理信息 4 日志记录 5 释放锁1 局部变量{intstatus;char*process;ngx_pid_tpid;ngx_err_terr;ngx_int_ti;ngx_uint_tone;one0;one标记是否已成功回收过至少一个子进程 初始化 one 为 0表示尚未回收任何子进程。2 循环 回收子进程for(;;){pidwaitpid(-1,status,WNOHANG);调用 waitpid 回收进程 -1等待任意子进程。 status获取子进程终止状态。 WNOHANG非阻塞模式若无已终止子进程则立即返回 0。 返回值 0成功回收的子进程 PID。 0尚有子进程在运行但无已终止的子进程。 -1出错需检查 errno。if(pid0){return;}pid 0 表示当前没有子进程处于可回收状态。 说明所有已退出的子进程都已处理完毕安全退出循环。if(pid-1){errngx_errno;if(errNGX_EINTR){continue;}INTR 表示 waitpid() 被其他信号中断。 则重新尝试 waitpidif(errNGX_ECHILDone){return;}ECHILD 表示“没有子进程”。 one 1 表示已经成功回收过至少一个子进程。 如果已经成功回收过至少一个子进程one 1 且仍收到 ECHILD说明是操作系统对已回收进程的冗余信号通知见下方注释 此时可安全退出循环。 这是对 Solaris/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(errNGX_ECHILD){ngx_log_error(NGX_LOG_INFO,ngx_cycle-log,err,waitpid() failed);return;}#1 注释说明Solaris 和 FreeBSD 等系统存在信号投递的“过度调用”问题 同一个退出事件可能多次触发 SIGCHLD或所有子进程都已回收后仍触发信号 Nginx 必须兼容这些历史行为。 #2 此时 one 0 且 err ECHILD说明一个子进程都没回收但系统报告无子进程。 这通常是上述 OS quirks 导致的属于预期内的边界情况记录 INFO 日志后返回。ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,err,waitpid() failed);return;}其他非预期错误如 EINVAL、EFAULT 等记录 ALERT 级别日志并返回。3 更新进程管理信息one1;processunknown process;#1 执行到这里说明 pid 0已成功回收一个子进程将 one 置为 1 后续再遇到 ECHILD 将直接返回。 #2 process unknown process 默认名称。如果 PID 不在 Nginx 进程表中则以此名称记录日志。for(i0;ingx_last_process;i){if(ngx_processes[i].pidpid){ngx_processes[i].statusstatus;ngx_processes[i].exited1;processngx_processes[i].name;break;}}遍历 ngx_processes 全局数组 ngx_last_process 是当前已创建的进程槽位数。 匹配到 PID 后 保存子进程的退出状态 status。 标记 exited 1表示该进程已退出 获取该进程名称例如 worker process、cache manager process用于日志输出。 若未找到匹配项process 仍为 unknown process这通常不应发生但作为一种防御性编程存在。4 日志记录if(WTERMSIG(status)){#ifdefWCOREDUMPngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,%s %P exited on signal %d%s,process,pid,WTERMSIG(status),WCOREDUMP(status)? (core dumped):);#elsengx_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));}if(WEXITSTATUS(status)2ngx_processes[i].respawn){ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,%s %P exited with fatal code %d and cannot be respawned,process,pid,WEXITSTATUS(status));ngx_processes[i].respawn0;}#1 if (WTERMSIG(status)) { WTERMSIG 是一个用于解析进程退出状态的宏函数。 它的作用是从 wait 或 waitpid 函数返回的 status 参数中提取导致子进程异常终止的信号编号。 必须先通过 WIFSIGNALED(status) 确认子进程确实是被信号终止的 否则调用 WTERMSIG 的结果是未定义行为可能返回随机值或崩溃。 只有在 WIFSIGNALED(status) 宏返回真非零时 调用 WTERMSIG(status) 才有意义。WIFSIGNALED 用于判断子进程是否是被某个信号杀死的。 返回值返回 int 类型的信号编号 返回导致子进程终止的信号编号例如 SIGKILL 是 9SIGSEGV 是 11。 返回 0 子进程正常退出时 子进程通过 exit() 等方式自然结束而非被信号杀死 此 if 判断子进程是否因信号而异常终止。#2 记录因信号退出的日志级别 ALERT#3 若未被信号终止则为正常退出 记录正常退出日志级别 NOTICE#4 特殊退出码处理 Nginx 约定退出码 2 表示“致命错误” 将 respawn 0关闭自动重启机制 WEXITSTATUS 是一个用于解析进程退出状态的宏函数。 它的作用是从 wait 或 waitpid 返回的 status 值中 提取子进程正常退出时的退出码即 exit(n) 中的 n 或 main 函数的返回值。5 释放锁ngx_unlock_mutexes(pid);}}解锁该子进程持有的所有互斥锁

更多文章