onWorkerStop 是正常退出,onWorkerError 是异常崩溃;前者在进程体面退场时触发,仅含 $server 和 $worker_id 参数,用于清理资源;后者在致命错误或信号强制终止时触发,含 $worker_pid、$exit_code、$signal,必须用于告警和错误记录。

onWorkerStop 是正常退出,onWorkerError 是异常崩溃 —— 两者触发条件、参数含义和处理方式完全不同,混用会导致监控失效或资源泄漏。
onWorkerStop:进程被主动终止或达到 max_request 时触发
这个回调只在 Worker/Task 进程“体面退场”时执行,比如调用 kill $pid、配置了 max_request 且已处理完指定请求数、或 Manager 主动回收旧进程准备 reload。
-
onWorkerStop的参数只有两个:$server和$worker_id,不提供退出原因 - 它不区分是 Worker 还是 Task 进程,只要设置了
task_worker_num > 0,Task 进程也会触发该事件(但注意:Task 进程不会触发onWorkerError) - 适合做清理工作:关闭数据库连接、释放文件句柄、写入日志记录“平滑退出”
- 不能依赖它捕获崩溃信息 —— 它根本不知道进程为什么停
onWorkerError:进程因致命错误或信号被强制杀死时触发
这是真正的“事故现场记录仪”,仅当 Worker/Task 进程非正常死亡时由 Manager 进程回调,比如 PHP 中出现未捕获的 Fatal error、调用了 exit()、被 kill -9 或 kill -11 终止。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 参数完整:除了
$server和$worker_id,还有$worker_pid、$exit_code、$signal -
$exit_code可判断是否为 PHP 错误退出(如 255 常见于 fatal error),$signal能识别是被哪个信号干掉的(9是 SIGKILL,11是 SIGSEGV) - 务必在这里做告警:发钉钉/企业微信消息、写入独立错误日志、上报 Prometheus 指标
- 不要在该回调里尝试恢复或重连资源 —— 进程已死,此时只能记录,后续由 Manager 新启进程接管
为什么 onWorkerError 不会触发 onWorkerStop?
这两个事件走的是完全不同的退出路径。onWorkerError 是 Manager 捕获子进程 signal 或 waitpid 返回异常状态后立即回调;而 onWorkerStop 是进程自己调用 exit() 或完成 max_request 后,向 Manager 发送退出信号,Manager 收到后才回调。
- 一个进程崩溃(如 segfault)→ Manager 收到 SIGCHLD + waitpid 得到非零状态 → 触发
onWorkerError→ 立即 fork 新进程替代 - 一个进程完成 1000 次请求(
max_request=1000)→ 进程自行exit(0)→ Manager 收到正常退出信号 → 触发onWorkerStop - 如果在
onWorkerError里手动调用了exit(),那不会再次触发onWorkerStop—— 因为进程已经死了,Manager 不会再等它“优雅退出”
容易忽略的关键点
很多人以为只要写了 onWorkerStop 就能覆盖所有退出场景,但实际线上最需要关注的是那些没留下堆栈就消失的 Worker —— 它们只会进 onWorkerError,而且默认情况下你根本收不到任何通知。
-
onWorkerError默认不打印任何信息,必须显式写日志或告警,否则等于没开 - Task 进程也会触发
onWorkerError,但不会触发onWorkerStop(Swoole 文档明确说明:only Worker processes triggeronWorkerStop) - 在
onWorkerStart中 require 的文件,若在运行中被修改,Worker 崩溃重启后加载的是新代码 —— 所以onWorkerError频发可能意味着刚上线有 bug

















