fatal error会导致worker进程立即退出,manager拉起新进程;onworkererror仅通知进程退出,需依$signal和$exitcode判断原因;max_request不宜设0;协程内fatal error可能不终止worker,须在协程入口手动注册shutdown函数。

Worker进程里Fatal Error会直接退出,不是抛异常
PHP的Fatal Error(比如调用未定义函数、内存溢出、类不存在)不会触发try/catch,也不会走set_exception_handler。它会让当前Worker进程立即终止,Manager进程检测到退出后拉起新进程——这个过程用户无感知,但日志里会出现worker_id=3 exited, code=255, signal=0这类记录。
容易踩的坑:
- 在
onWorkerStart外注册register_shutdown_function,它根本不会生效——必须每个Worker自己注册 -
error_get_last()返回null时直接取$error['message']会报Notice,得先判空 - 没打上
$workerId和时间戳的日志,在多进程环境下完全没法对应到具体崩溃点
onWorkerError回调只对致命退出有效,且参数含义要分清
onWorkerError事件不是“捕获错误”,而是“收到进程退出通知”。它在Worker因Fatal Error、SIGSEGV、OOM kill等导致进程死亡后由Manager触发,回调参数顺序是($server, $workerId, $workerPid, $exitCode, $signal)。
关键判断依据:
-
$signal === 11→SIGSEGV,大概率C扩展或内存越界,要开core dump -
$signal === 9→SIGKILL,优先查dmesg -T | grep "killed process"确认是否OOM Killer干的 -
$exitCode === 255且$signal === 0→ 典型PHP Fatal Error,配合register_shutdown_function查具体哪行
max_request设为0反而放大Fatal Error影响
把max_request配成0,等于让Worker无限复用。一旦有静态变量污染、资源句柄泄漏或缓存累积,不出几小时就可能触发OOM或栈溢出,最终以Fatal Error形式崩掉——而且每次崩的位置还不一样,极难复现。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
实操建议:
- 生产环境别用0,常规服务设
1000–5000,高内存消耗场景(如图像处理)压到200–500 - 如果发现Worker总在接近
max_request值时退出,说明不是配置问题,而是真有泄漏,该翻代码了 - 搭配
max_request_grace使用,避免正在处理的请求被硬中断
协程里触发Fatal Error更隐蔽
在Swoole协程中(比如go(function () { ... })),一个未捕获的Fatal Error只会终结当前协程,不一定会让整个Worker退出。但若错误发生在协程启动前(如go回调函数体解析失败)、或协程内调用了扩展级崩溃操作(如某些C扩展的非法指针访问),Worker仍会整条命丢掉。
所以不能只依赖onWorkerError:必须在每个协程入口手动包一层register_shutdown_function,且确保error_get_last()能拿到协程上下文里的最后错误——这点在PHP 8.1+协程调度器下尤其容易漏。
真正难缠的,是那个在onWorkerStart里注册了兜底函数,却因为某次协程里exit()或die()提前结束,导致后续请求永远收不到错误日志的Worker。










