segmentation fault (core dumped) 是c层段错误,php层try/catch无效,常见于swoole扩展abi不匹配、协程不安全操作或内存越界;需启用core dump并用gdb分析调用栈定位根本原因。

Segmentation fault (core dumped) 在 Swoole 里不是 PHP 层能 catch 的错误
它直接来自 C 扩展层,意味着 try/catch 或 set_exception_handler 完全无效。你看到的崩溃日志里只有 Worker进程因信号11崩溃、Segmentation fault (core dumped),没有堆栈、没有行号——这不是代码逻辑错,是内存被非法触碰了。
常见触发点集中在底层资源误用:比如在协程里混用非协程安全的扩展(如某些老版本 pdo_mysql)、手动调用 swString_append 时传入已释放的字符串指针、或 coroutine::get_context() 返回空上下文后强行解引用。
- PHP 层异常可捕获、可记录、可重试;段错误会直接 kill 进程,靠 Manager 进程拉起新 Worker,但状态丢失不可逆
- 崩溃位置往往不在你写的业务代码里,而在 Swoole 内部函数或第三方扩展的 C 实现中
- 同一份代码,在 CLI 模式下运行正常,开协程后随机崩,大概率是扩展 ABI 不兼容或线程/协程不安全操作
core dump 文件生成和分析必须手动开启且限定路径
Linux 默认禁用 core dump,Swoole Worker 崩溃时不会自动生成 core 文件——你得先确认系统允许,并指定明确路径,否则 gdb 无从下手。
执行这两步缺一不可:
-
ulimit -c unlimited(当前 shell 会话生效) -
echo "/tmp/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern(把所有 core 写进/tmp/,避免权限或磁盘满导致写失败)
之后用 gdb /path/to/php /tmp/core.php.12345 加载,再输入 bt 看崩溃时的 C 调用栈。注意:必须用和运行时完全一致的 PHP 二进制文件(含调试符号),否则帧信息全是问号。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
Swoole 版本 + PHP ABI 匹配是高频隐形雷区
很多段错误根本不是你代码的问题,而是 swoole.so 和当前 PHP 的 ABI(Application Binary Interface)不匹配。典型表现:压测跑一阵后随机崩在 swString_append 或 swReactorEpoll_add,重启后暂时恢复,几小时后复现。
验证方式很简单:
- 运行
php --ri swoole | grep "PHP Version",确认输出的 PHP 版本和php -v一致 - 检查是否用了项目自带的
swoole-loader—— 如果没用,说明你加载的是全局安装的swoole.so,它极可能编译于另一个 PHP 版本或构建参数 - 升级 PHP 后务必重新
pecl install swoole,不能复用旧的.so
别信“稳定复现”,段错误的随机性本身就是线索
同一个请求、同一段代码,有时崩、有时不崩,不代表问题不存在——恰恰说明是野指针、竞态访问或内存越界这类非确定性错误。比如:
- 协程 A 中释放了某块内存,协程 B 还拿着指针去读,B 执行时机决定是否踩到已回收页
- 数组越界写到了相邻变量的内存,而那个变量是否被后续代码读取,决定了是否立即暴露
- 使用了未加
SWOOLE_HOOK_ALL的扩展,底层 socket 被阻塞,协程调度器失序,最终在某个清理阶段触发非法访问
这种非确定性,正是段错误最难缠的地方:它不报错时像没病,一报就是致命伤。盯住崩溃前最后几条日志、core 中的寄存器值(尤其是 $rdi、$rsi 是否为 0 或明显非法地址),比反复复现更有效。








