news 2026/4/18 0:51:17

ngx_process_get_status

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ngx_process_get_status

1 定义

ngx_process_get_status 函数 定义在 ./nginx-1.24.0/src/os/unix/ngx_process.c
staticvoidngx_process_get_status(void){intstatus;char*process;ngx_pid_tpid;ngx_err_terr;ngx_int_ti;ngx_uint_tone;one=0;for(;;){pid=waitpid(-1,&status,WNOHANG);if(pid==0){return;}if(pid==-1){err=ngx_errno;if(err==NGX_EINTR){continue;}if(err==NGX_ECHILD&&one){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(err==NGX_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;}one=1;process="unknown process";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;}}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)==2&&ngx_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].respawn=0;}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;one=0;
one:标记是否已成功回收过至少一个子进程 初始化 one 为 0,表示尚未回收任何子进程。

2 循环 回收子进程
for(;;){pid=waitpid(-1,&status,WNOHANG);
调用 waitpid 回收进程 -1:等待任意子进程。 &status:获取子进程终止状态。 WNOHANG:非阻塞模式,若无已终止子进程则立即返回 0。 返回值: > 0:成功回收的子进程 PID。 0:尚有子进程在运行,但无已终止的子进程。 -1:出错(需检查 errno)。

if(pid==0){return;}
pid == 0 表示当前没有子进程处于可回收状态。 说明所有已退出的子进程都已处理完毕,安全退出循环。

if(pid==-1){err=ngx_errno;if(err==NGX_EINTR){continue;}
INTR 表示 waitpid() 被其他信号中断。 则重新尝试 waitpid

if(err==NGX_ECHILD&&one){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(err==NGX_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 更新进程管理信息
one=1;process="unknown process";
#1 执行到这里说明 pid > 0,已成功回收一个子进程,将 one 置为 1 后续再遇到 ECHILD 将直接返回。 #2 process = "unknown process": 默认名称。如果 PID 不在 Nginx 进程表中,则以此名称记录日志。

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;}}
遍历 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)==2&&ngx_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].respawn=0;}
#1 if (WTERMSIG(status)) { WTERMSIG 是一个用于解析进程退出状态的宏函数。 它的作用是从 wait 或 waitpid 函数返回的 status 参数中,提取导致子进程异常终止的信号编号。 必须先通过 WIFSIGNALED(status) 确认子进程确实是被信号终止的, 否则调用 WTERMSIG 的结果是未定义行为(可能返回随机值或崩溃)。 只有在 WIFSIGNALED(status) 宏返回真(非零)时, 调用 WTERMSIG(status) 才有意义。WIFSIGNALED 用于判断子进程是否是被某个信号杀死的。 返回值:返回 int 类型的信号编号 返回导致子进程终止的信号编号(例如 SIGKILL 是 9,SIGSEGV 是 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);}}
解锁该子进程持有的所有互斥锁
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 0:50:14

贾子逆算子(KIO)全解:从理论定义到工程修正的完整实现

贾子逆算子&#xff08;KIO&#xff09;全解&#xff1a;从理论定义到工程修正的完整实现摘要贾子逆算子&#xff08;KIO&#xff09;是2026年初提出的大语言模型主动式幻觉抑制元算子&#xff0c;通过逆向映射与因果追溯实现逻辑校准&#xff0c;推动模型从“概率生成”转向“…

作者头像 李华
网站建设 2026/4/18 0:39:31

如何实现跨设备音频共享?Scream虚拟声卡网络传输终极指南

如何实现跨设备音频共享&#xff1f;Scream虚拟声卡网络传输终极指南 【免费下载链接】scream Virtual network sound card for Microsoft Windows 项目地址: https://gitcode.com/gh_mirrors/sc/scream 你是否曾想过将电脑音频无线传输到其他设备播放&#xff1f;无论是…

作者头像 李华
网站建设 2026/4/18 0:39:27

微机原理实验一代码逐行“翻译”:从汇编指令到C语言思维帮你理解

从汇编到C&#xff1a;微机原理实验代码的思维转换指南 1. 汇编与C语言的桥梁搭建 第一次接触微机原理实验的同学们&#xff0c;往往会被那些密密麻麻的汇编指令弄得晕头转向。mov ax, data、int 21h这些看似神秘的代码&#xff0c;其实都有其对应的C语言思维模式。让我们从一个…

作者头像 李华
网站建设 2026/4/18 0:35:07

矩阵的“度量衡”——行列式:从定义到计算的本质探索

1. 行列式&#xff1a;矩阵世界的"标尺" 想象你手里有一把神奇的尺子&#xff0c;它不仅能测量长度&#xff0c;还能测量一个矩阵的"大小"和"性质"。这把尺子就是行列式。对于初学者来说&#xff0c;行列式可能看起来像一堆复杂的数学符号&#…

作者头像 李华