先把当时的情况摆出来。CentOS 7.9 + PHP 7.4 装了图像处理扩展,导出两千万像素大图时偶发五零二,php-fpm error.log 里只有 child 8123 exited on signal 11 (Segmentation fault),nginx 侧写 upstream prematurely closed connection。

原因不止一个,得分开看。扩展内部的缓冲区按固定尺寸分配,超过预期尺寸的图片直接越界写坏内存。少数情况下是图片解析走了递归,层数一深把进程栈撑爆,表现同样是段错误。

不容易想到的是,扩展版本与当前 PHP 小版本不匹配,符号对不上,调用到错误地址。还有一种情况,opcache 里存着旧版本扩展编译出的字节码,热更新后同一脚本行为不一致。

上来先确认崩溃集中在哪些脚本和参数

grep -E 'signal 11|Segmentation' /var/log/php-fpm/error.log | tail -20

然后打开核心转储,留存崩溃现场

sysctl -w kernel.core_pattern=/data/core/core.%e.%p && ulimit -c unlimited

拿到转储后用调试符号看调用栈

gdb -batch -ex 'bt' /usr/sbin/php-fpm /data/core/core.php-fpm.8123

等前面都确认过,再把可疑扩展降一个版本再压测

yum downgrade -y php-pecl-imagick && systemctl restart php-fpm

怎么算真的好了,看的是同一批现象。同一张大图连续导出五十次不再出现五零二,error.log 里没有新的 signal 11,/data/core 下不再生成新的转储文件。

补一句。段错误多半在扩展里,别在业务代码上反复改;核心转储占空间,定位完记得把 core_pattern 改回去。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189