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

PHP 內核 Bug:動態載入擴展全域變數析構導致 Core Dump

     編輯:PHP 綜合知識

動態載入(.so)的 PHP 擴展在模組卸載時,若註冊了全域變數析構函數(dtor),會因模組已被 DL_UNLOAD 卸載導致函數指標失效,觸發 Core Dump。此問題僅發生於動態載入擴展,靜態編譯不受影響。

問題重現條件

  • 擴展以 shared 方式編譯(產生 .so)
  • 使用 ZEND_MODULE_GLOBALS_DTOR_N 註冊全域變數析構函數
  • 啟用 ZTS(線程安全)

調用堆疊追蹤

zend_shutdown()
  → zend_destroy_modules()
  → zend_hash_graceful_reverse_destroy()
  → zend_hash_apply_deleter()
  → module_destructor()
  → DL_UNLOAD(module->handle)  // 模組先被卸載
  → tsrm_shutdown()            // 此時才呼叫 dtor,但代碼已不在記憶體

根本原因

Zend 引擎關閉流程中,先卸載模組再關閉 TSRM,導致動態載入擴展的 dtor 回調函數在被呼叫時,其所屬代碼段已被釋放。

解決方案與規避策略

  1. 靜態編譯擴展:避免動態載入/卸載流程(官方標準擴展皆採此法)
  2. 不註冊 dtor:若全域資源無需顯式釋放(如純量資料),可省略 dtor 註冊
  3. 手動資源管理:在 RSHUTDOWN 階段主動釋放資源,不依賴 TSRM 關閉時的 dtor
  4. 升級 PHP 版本:PHP 7+ 重寫了模組管理機制,緩解此問題

此為 PHP 5 時代已知內核缺陷,開發動態擴展時務必注意模組卸載順序與資源生命週期管理。

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