Master进程通过内核发送的SIGCHLD信号感知Worker退出,再调用非阻塞waitpid获取状态,依据WIFSIGNALED或非零退出码判断异常并拉起新进程,正常退出则仅清理。

Nginx 的 Master 进程本身不接收 Worker 主动“上报”的异常事件,它也不依赖任何心跳、日志或 RPC 机制来获知 Worker 状态。所谓“异常事件上报”,实际是操作系统内核通过 SIGCHLD 信号向 Master 发出的被动通知,Master 再主动调用 waitpid() 获取真实退出原因——整个过程是异步、轻量、由内核保障的底层机制。
Master 如何感知 Worker 异常终止
- 内核自动发送 SIGCHLD:只要任意 Worker 进程终止(无论
exit(1)、kill -SEGV $pid还是 OOM Killer 杀掉),内核都会立即向其父进程(即 Master)发送 SIGCHLD - Master 不轮询、不监听端口、不建连接:它不主动探测 Worker 是否卡死或响应慢;Worker 停滞但未退出时,Master 完全无感
- 信号处理只设标志位:Master 的
ngx_signal_handler收到 SIGCHLD 后,仅设置ngx_reap = 1,避免在信号上下文中做复杂操作(如调用waitpid可能阻塞或引发重入问题)
Master 如何提取并判断异常退出原因
- 在主事件循环中调用
ngx_process_get_status():检查ngx_reap标志,再遍历内部进程表ngx_processes - 对每个已标记为
exited或exiting的 Worker,执行waitpid(pid, &status, WNOHANG)-
WNOHANG确保非阻塞:若子进程资源尚未完全释放,就跳过,下次再试
-
- 从
status中解析关键信息:-
WIFSIGNALED(status)为真 → 被信号终止:进一步看WTERMSIG(status),如值为 11(SIGSEGV)、6(SIGABRT)、9(SIGKILL)等,即属异常崩溃 -
WIFEXITED(status)为真且WEXITSTATUS(status) != 0→ 非零退出码:常见于 Worker 主动调用exit(1)(如配置加载失败、模块初始化出错) -
WIFEXITED(status)为真且WEXITSTATUS(status) == 0→ 正常退出:如nginx -s reload后旧 Worker 处理完请求优雅退出
-
Master 如何响应异常退出
- 立即拉起新 Worker:只要确认是异常退出(非零退出码或致命信号),Master 就 fork + exec 启动一个新进程,继承监听套接字和配置上下文
-
频率熔断保护:Master 统计最近 1 秒内异常退出次数
- 若 ≥ 10 次(硬编码阈值),Master 自行退出,并记录日志
"exit after too many worker processes exit unexpectedly" - 此时需人工介入:查 core dump、检查配置语法、排查第三方模块冲突或内存越界
- 若 ≥ 10 次(硬编码阈值),Master 自行退出,并记录日志
-
不干预正常退出:对
SIGQUIT、SIGTERM或 reload 触发的exit(0),Master 仅清理进程表条目,不告警、不拉起、不记录 error 日志
异常事件的可观测性边界在哪里
- Master 日志里体现的是 信号名 + PID + 是否 respawn,例如:
2026/06/29 12:15:22 [alert] 12345#0: worker process 56789 exited on signal 11 (core dumped) - 退出码本身不用于决策,也不透传给监控系统;真正有价值的是终止信号类型和发生频次
- 若需发现“卡死”类问题(如 Worker 占用 CPU 100% 但不退出),必须依赖外部工具:
top、strace -p $pid、gdb attach $pid或 Prometheus + nginx-module-vts 暴露的活跃连接数指标
不复杂但容易忽略


















