segmentation fault 是 c 层段错误,php 无法捕获;主因是 swoole.so 与 php abi 不匹配、混用 swoole_loader 或 swow、调用废弃 c api 等;须通过 php --ri swoole 核对编译版本、重编译扩展、禁用冲突模块,并启用 core dump 配合 gdb 定位。

Segmentation fault 是 C 层崩溃,不是 PHP 代码能 catch 的
看到 Segmentation fault (core dumped) 就别在 PHP 里加 try-catch 或查日志了——这已经掉出 PHP 执行层,是 Swoole 扩展或其依赖的底层 C 模块访问了非法内存地址。常见触发点包括:Swoole.so 与当前 PHP ABI 不匹配、混用不同版本的 swoole-loader、手动调用了已废弃的 C API(如 swTimer_add)、或 Swow/Swoole 扩展同时加载冲突。
先验证 Swoole 编译环境是否匹配 PHP
执行 php --ri swoole | grep -E "Version|compiled",重点比对两行:
-
Version => 5.1.1(你装的版本) -
compiled with php version => 8.1.27(编译时用的 PHP 版本)
如果第二行显示的是 8.0.30 或 8.2.0,而你当前运行的是 8.1.27,就必然崩。这不是“差不多就行”,ABI 不一致会导致结构体偏移错乱,随机 segfault。
实操建议:
- 删掉现有 swoole.so:
sudo rm /usr/lib/php/20210902/swoole.so(路径以php-config --extension-dir输出为准) - 用当前 PHP 重新编译:
cd swoole-src && phpize && ./configure --enable-coroutine && make && sudo make install - 确认
php -m | grep swoole有输出,且php --ri swoole中 compiled 版本与php -v完全一致
检查是否误启了 swoole_loader 或混用 Swow
Hyperf 3.1 默认不带 swoole_loader,但如果你项目里手动引入过(比如从旧版迁移),或 php.ini 里写了 extension=swoole_loader.so,它会劫持类加载并破坏协程上下文,尤其在多 Worker 场景下极易触发段错误。
同样,Swow 和 Swoole 不能共存:php -m 同时出现 swoole 和 swow 就是高危信号。Hyperf 官方只保证单引擎支持,双扩展加载后,coroutine::create 可能调到 Swow 的栈管理,而 Server::start 却走 Swoole 的 eventLoop,底层资源打架必崩。
快速排查:
- 执行
php -m | grep -E "(swoole|swow)",只留一个 - 搜
php.ini:grep "swoole_loader\|swow" $(php --ini | grep "Loaded Configuration File" | cut -d' ' -f4) - 注释掉无关 extension 行,重启 PHP-FPM 或 Hyperf 进程
启用 core dump 定位具体崩溃点
默认 Linux 不生成 core 文件,得先放开限制:
- 临时生效:
ulimit -c unlimited && export CORE_PATTERN="/tmp/core.%e.%p" - 在
config/autoload/server.php的settings里加:'core_dump' => true - 复现崩溃后,用
gdb php /tmp/core.hyperf.*,输入bt看堆栈,重点关注最后一层是不是swString_append、coroutine::get_context或php_swoole_server_onStart
如果堆栈指向 ext/redis 或 ext/memcached,说明这些扩展没适配协程,得换 hyperf/redis 或 hyperf/metric 的协程封装层——原生扩展在常驻进程中反复初始化会踩内存。
真正难缠的 segfault 往往藏在“看起来没问题”的地方:比如某处用了 static $cache = [] 存 PDOStatement,协程切换后句柄失效;或者自定义进程里调了 pcntl_fork(),子进程继承了 Swoole 的 epoll 实例却没重置。这类问题不会报错,但跑几小时后必然崩。别迷信日志,得靠 core + gdb 定点爆破。











