segmentation fault是c层段错误,无法用php try/catch捕获,需检查core dump、swoole abi兼容性、disable_functions禁用pcntl/posix函数及workerman调试日志。

Workerman 出现 Segmentation fault,基本可以确定不是 PHP 业务代码抛出的异常,而是底层 C 扩展(如 swoole、pcntl 或 Workerman 自身依赖的扩展)发生了内存访问违规,直接被操作系统终止。这类错误无法用 try/catch 捕获,日志里通常只有一行 Segmentation fault (core dumped),必须从系统级调试入手。
查 core dump 文件是否存在并加载分析
Linux 默认禁用 core dump,所以第一步不是看日志,而是确认是否生成了 core 文件:
- 运行
ulimit -c,输出为0表示禁止生成;执行ulimit -c unlimited临时开启(注意:仅对当前 shell 有效) - 检查
/proc/sys/kernel/core_pattern确认 core 文件落盘路径,常见如/var/lib/apport/coredump/core.%e.%p.%h.%t或直接写到当前目录 - 找到 core 文件后,用
gdb php core.xxx加载,再输入bt查看崩溃时的调用栈——重点看是否卡在swString_append、coroutine::get_context、pcntl_fork或posix_kill等函数内 - 若 core 文件太大或生产环境不允许开启,跳过此步,但需知道:没 core 就等于少了一张关键 X 光片
验证 PHP 扩展 ABI 兼容性(尤其 Swoole)
Workerman 虽不强制依赖 Swoole,但很多项目混用 Swoole 扩展;而 Segmentation fault 在 Swoole 场景下最常源于 ABI 不匹配:
- 运行
php --ri swoole,确认Version和PHP Version是否匹配;例如 PHP 8.2 编译的 Swoole.so 不能用于 PHP 8.3 - 检查是否用了项目自带的
swoole-loader文件——它通常做了 ABI 对齐,而系统全局安装的swoole.so很可能版本错位 - 临时卸载 Swoole:
sudo phpdismod swoole,再启动 Workerman;如果不再段错误,基本锁定是 Swoole 扩展问题 - 重装 Swoole 时务必指定 PHP 配置路径:
phpize && ./configure --with-php-config=/usr/bin/php-config && make && sudo make install
检查 disable_functions 是否拦住了关键系统调用
Workerman 的 master-worker 模型严重依赖 pcntl 和 posix 系列函数,一旦被禁用,master 进程可能在 fork 子进程时直接崩溃为段错误:
- 运行
php -i | grep disable_functions,确认输出中不含pcntl_fork、pcntl_waitpid、posix_kill、posix_getpid - 特别注意某些云主机或 Docker 镜像默认禁用这些函数(出于安全限制),即使 Workerman 启动脚本里写了
pcntl_fork(),也会触发内核信号 11 - 临时测试可注释掉
disable_functions行,重启 PHP-FPM 或 CLI 环境后重试;确认后再按最小权限原则放开必要函数 - 别只信
phpinfo()页面——CLI 和 FPM 的配置文件可能不同,用php -c /path/to/cli.ini -i显式指定 CLI 配置再查
开启 Workerman 调试日志 + 强制 PHP 错误输出
Workerman 默认不把 PHP 层 fatal error 输出到终端或日志,容易掩盖真正崩溃前的线索:
- 在
start.php最顶部加三行:ini_set('display_errors', 'on');、error_reporting(E_ALL);、use Workerman\Config; Config::$debug = true; - 这样能让
workerman.log记录 worker 启动/退出事件,同时 fatal error 会打到 stdout(守护进程模式下需配合nohup或重定向查看) - 避免用
var_dump()或echo调试——它们输出位置不可控;改用file_put_contents('/tmp/workerman_debug.log', print_r($x, true)."\n", FILE_APPEND) - 如果
workerman.log里出现exit with status 256,那是 PHP 子进程被信号 1 终止(如调用禁用函数),和Segmentation fault(信号 11)性质不同,不要混淆排查路径
段错误本质是内存越界或非法访问,Workerman 场景下极少由纯 PHP 代码引发;真正要盯住的是扩展兼容性、系统调用权限、以及 core dump 提供的底层调用栈——没有 core,就等于在黑屋子里找开关,只能靠排除法一层层关灯。











