首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP-FPM 進程 SIGBUS 故障排查:coredump 分析與 opcache 衝突根因

     編輯:PHP 相關知識

PHP-FPM 進程 SIGBUS 故障排查:coredump 分析與 opcache 衝突根因

生產環境 PHP-FMP 子進程頻繁收到 SIGBUS (signal 7) 退出,Nginx 回傳 502。本文記錄完整排查過程:開啟 coredump、gdb 回溯、strace 系統調用追蹤、鎖定 opcache 衝突根因並給出解決方案。

現象

  • php-fpm.log 大量 child exited on signal 7 (SIGBUS)。
  • 高峰期更頻繁,排除進程數不足、記憶體耗盡、APC 等擴展問題。

開啟 coredump 捕獲

# 設定 core 檔案路徑與命名格式
echo "/tmp/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern
# 允許無限大 core
ulimit -c unlimited
# 重啟 php-fpm
systemctl restart php-fpm

gdb 分析 coredump

gdb /usr/local/php/sbin/php-fpm /tmp/core.php-fpm.12345
(gdb) bt
#0  0x00007f... in lex_scan () from /usr/local/php/lib/php/opcache.so
#1  0x00007f... in zendlex ()
#2  0x00007f... in zendparse ()
...
# 多個 core 皆停在 lex_scan / zendlex 階段

Google 關鍵字定位

搜尋 php sigbus lex_scan 直指 PHP 官方 Bug #52752(2010 年開啟,長期未修):

  • 原因:PHP 檔案在被編譯執行 (lex_scan) 過程中,被其他進程覆寫/截斷(如部署腳本 cp/rsync、opcache 重新編譯、框架熱更新)。
  • 記憶體映射 (mmap) 的檔案發生截斷,CPU 讀取無效位址觸發 SIGBUS。

strace 實錘

strace -p  -f -o trace.log
# 事故瞬間日誌:
11670 lstat("/home/www/cache/default.php", {st_size=68579, ...}) = 0
11670 --- SIGBUS (Bus error) @ 0 (0) ---

確認是讀取快取檔 default.php 時觸發。

解決方案

  1. 原子性部署:新版本寫入暫存目錄 → rename() 原子替換舊檔,避免讀寫並發。
  2. opcache 設定優化:
    opcache.validate_timestamps=0   # 生產關閉時間戳驗證,手動重啟或 cachetool 刷新
    opcache.revalidate_freq=0       # 配合上面
    opcache.file_cache_only=1       # 僅用檔案快取,避免共享記憶體衝突 (可選)
    
  3. 避免運行時寫入 PHP 檔案:框架快取、模板編譯輸出至 /tmp 或獨立目錄,不與代碼目錄混用。

驗證

調整部署腳本採用 rsync --delay-updates + mv 原子切換,並關閉 validate_timestamps,連續觀察一週無 SIGBUS 復發。

參考資源

總結

SIGBUS 在 PHP 中幾乎等同於「執行中的腳本檔案被外部修改」。生產環境務必採用**原子性部署**、關閉 opcache 時間戳驗證、隔離可寫快取目錄,從架構層面杜絕此類硬故障。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved