php的core問題,net core php

本文目錄一覽:

ThinkPHP3.2入口文件引入出錯,求大神

這個入口文件,引用的是相對路徑。

①首先,你要確定和index.php同級的目錄下有沒有core文件夾,如果有,進去看看有沒有ThinkPHP.php。

②如果core目錄和index.php不同級,就要根據相對路徑去計算,如何定位到core文件夾。

這個問題是小問題,仔細一點,好好拍查一下。

如何調試PHP的Core之獲取基本信息

在這個過程中, 會涉及到對PHP的函數調用, PHP的傳參, PHP的一些全局變數的知識.

首先, 讓我們生成一個供我們舉例子的Core文件:

?php

function recurse($num) {

recurse(++$num);

}

recurse(0);

運行這個PHP文件:

$ php test.php

Segmentation fault (core dumped)

這個PHP因為無線遞歸, 會導致爆棧, 從而造成 segment fault而在PHP的當前工作目錄產生Coredump文件(如果你的系統沒有產生Coredump文件, 那請查詢ulimit的相關設置).

現在刪除掉這個test.php, 忘掉上面的代碼, 我們現在僅有的是這個Core文件, 任務是, 找出這個Core產生的原因, 以及發生時候的狀態.

首先, 讓我們用gdb打開這個core文件:

$ gdb php -c core.31656

會看到很多的信息, 首先讓我們注意這段:

Core was generated by `php test.php’.

Program terminated with signal 11, Segmentation fault.

他告訴我們Core發生的原因:」Segmentation fault」.

一般來說, 這種Core是最常見的, 解引用空指針, double free, 以及爆棧等等, 都會觸發SIGSEGV, 繼而默認的產生Coredump.

現在讓我們看看Core發生時刻的堆棧:

#0 execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:53

53 memset(EX(CVs), 0, sizeof(zval**) * op_array-last_var);

(gdb) bt

#0 execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:53

#1 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400210) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234

#2 0x00000000006e9f61 in execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:92

#3 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400440) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234

#4 0x00000000006e9f61 in execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:92

#5 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400670) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234

…..

不停的按回車, 可以看到堆棧很深, 不停的是zend_do_fcall_common_helper_SPEC和execute的重複, 那麼這基本就能斷定是因為產生了無窮大的遞歸(不能一定說是無窮遞歸, 比如我之前文章中介紹深悉正則(pcre)最大回溯/遞歸限制). 從而造成爆棧產生的Core.

Ok, 那麼現在讓我們看看, Core發生在PHP的什麼函數中, 在PHP中, 對於FCALL_* Opcode的handler來說, execute_data代表了當前函數調用的一個State, 這個State中包含了信息:

(gdb)f 1

#1 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400210) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234

234 zend_execute(EG(active_op_array) TSRMLS_CC);

(gdb) p execute_data-function_state.function-common-function_name

$3 = 0x2a95b65a78 “recurse”

(gdb) p execute_data-function_state.function-op_array-filename

$4 = 0x2a95b632a0 “/home/laruence/test.php”

(gdb) p execute_data-function_state.function-op_array-line_start

$5 = 2

現在我們得到, 在調用的PHP函數是recurse, 這個函數定義在/home/laruence/test.php的第二行

經過重複驗證幾個frame, 我們可以看出, 一直是在重複調用這個PHP函數.

要注意的是, 為了介紹查看執行信息的原理, 我才採用原生的gdb的print來查看, 其實我們還可以使用PHP源代碼中提供的.gdbinit(gdb命令編寫腳本), 來簡單的獲取到上面的信息:

(gdb) source /home/laruence/package/php-5.2.14/.gdbinit

(gdb) zbacktrace

[0xbf400210] recurse() /home/laruence/test.php:3

[0xbf400440] recurse() /home/laruence/test.php:3

[0xbf400670] recurse() /home/laruence/test.php:3

[0xbf4008a0] recurse() /home/laruence/test.php:3

[0xbf400ad0] recurse() /home/laruence/test.php:3

[0xbf400d00] recurse() /home/laruence/test.php:3

[0xbf400f30] recurse() /home/laruence/test.php:3

[0xbf401160] recurse() /home/laruence/test.php:3

…..

關於.gdbinit, 是一段小小的腳本文件, 定義了一些方便我們去調試PHP的Core, 大家也可以用文本編輯器打開, 看看裡面定義的一些快捷的命令, 一般來說, 我常用的有:

zbacktrace

print_ht**系列

zmemcheck

OK, 回歸正題, 我們現在知道, 問題發生在/home/laruence/test.php的recurse函數的遞歸調用上了.

現在, 讓我們來看看, 在調用這個函數的時候的參數是什麼?

PHP的參數傳遞是依靠一個全局Stack來完成的, 也就是EG(argument_stack), EG在非多線程情況下就是executor_globals, 它保持了很多執行狀態. 而argument_statck就是參數的傳遞棧, 保存著對應PHP函數調用層數相當的調用參數.

要注意的是, 這個PHP函數調用堆棧(層數)不和gdb所看到的backtrace簡單的一一對應, 所以參數也不能直接和gdb的backtrace對應起來, 需要單獨分析:

//先看看, 最後一次函數調用的參數數目是多少

(gdb) p (int )*(executor_globals-argument_stack-top_element – 2)

$13 = 1

//再看看, 最後一次函數調用的參數是什麼

(gdb) p **(zval **)(executor_globals-argument_stack-top_element – 3)

$2 = {value = {lval = 22445, dval = 1.1089303420906779e-319, str = {val = 0x57ad Address 0x57ad out of bounds, len = 7}, ht = 0x57ad, obj = {handle = 22445, handlers = 0x7}},

refcount = 2, type = 1 ‘\001’, is_ref = 0 ‘\0’}

好, 我們現在得到, 最後一次調用的參數是一個整數, 數值是22445

到了這一步, 我們就得到了這個Core發生的時刻的PHP層面的相關信息, 接下來, 就可以交給對應的PHP開發工程師來排查, 這個參數下, 可能造成的無窮大遞歸的原因, 從而修復這個問題..

如何查看php-fpm core dump 文件的錯誤

開啟php的coredump輸出,修改ulimit -c就可以了,但是很多情況下,會提示權利受限,無法修改

[fukun@10.16.29.xxx]$ ulimit -a

core file size (blocks, -c) 0

data seg size (kbytes, -d) unlimited

scheduling priority (-e) 0

file size (blocks, -f) unlimited

pending signals (-i) 30678

max locked memory (kbytes, -l) 64

max memory size (kbytes, -m) unlimited

open files (-n) 32768

pipe size (512 bytes, -p) 8

POSIX message queues (bytes, -q) 819200

real-time priority (-r) 0

stack size (kbytes, -s) 10240

cpu time (seconds, -t) unlimited

max user processes (-u) 1024

virtual memory (kbytes, -v) unlimited

file locks (-x) unlimited

$ ulimit -c unlimited

-bash: ulimit: core file size: cannot modify limit: Operation not permitted

解決方案:

1.檢查配置

看看shell配置里有沒有 ulimit -c 0 這種類似的關閉的操作,例如

$HOME/.bash_profile 或者 $HOME/.bashrc 之類的,如果有,注釋掉。

#

# Do not produce core dumps

#

# ulimit -c 0

2. 全局coredump開啟

使用root用戶,修改 /etc/security/limits.conf

# /etc/security/limits.conf

#

# Each line describes a limit for a user in the form:

#

# domain type item value

#

* soft core unlimited

3.退出並從新登錄shell,修改配置

ssh fukun@10.16.29.xxx

[fukun@10.16.29.xxx]$ ulimit

-c

先切換成root用戶進行設置

su –

ulimit -c unlimited

ulimit -c

unlimited

然後切換回自己的用戶進行設置

su – fukun

ulimit -c unlimited

ulimit -c

unlimited

以上3步有可能不是必須的,但是只要按這個步驟來,肯定能設置成功,在其它方法設置不成功的時候,按這個步驟來試試把。

原創文章,作者:DNNZ,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/148517.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
DNNZ的頭像DNNZ
上一篇 2024-11-03 15:16
下一篇 2024-11-03 15:16

相關推薦

  • Python官網中文版:解決你的編程問題

    Python是一種高級編程語言,它可以用於Web開發、科學計算、人工智慧等領域。Python官網中文版提供了全面的資源和教程,可以幫助你入門學習和進一步提高編程技能。 一、Pyth…

    編程 2025-04-29
  • PHP和Python哪個好找工作?

    PHP和Python都是非常流行的編程語言,它們被廣泛應用於不同領域的開發中。但是,在考慮擇業方向的時候,很多人都會有一個問題:PHP和Python哪個好找工作?這篇文章將從多個方…

    編程 2025-04-29
  • 如何解決WPS保存提示會導致宏不可用的問題

    如果您使用過WPS,可能會碰到在保存的時候提示「文件中含有宏,保存將導致宏不可用」的問題。這個問題是因為WPS在默認情況下不允許保存帶有宏的文件,為了解決這個問題,本篇文章將從多個…

    編程 2025-04-29
  • 解決.net 6.0運行閃退的方法

    如果你正在使用.net 6.0開發應用程序,可能會遇到程序閃退的情況。這篇文章將從多個方面為你解決這個問題。 一、代碼問題 代碼問題是導致.net 6.0程序閃退的主要原因之一。首…

    編程 2025-04-29
  • Java Thread.start() 執行幾次的相關問題

    Java多線程編程作為Java開發中的重要內容,自然會有很多相關問題。在本篇文章中,我們將以Java Thread.start() 執行幾次為中心,為您介紹這方面的問題及其解決方案…

    編程 2025-04-29
  • PHP怎麼接幣

    想要在自己的網站或應用中接受比特幣等加密貨幣的支付,就需要對該加密貨幣擁有一定的了解,並使用對應的API進行開發。本文將從多個方面詳細闡述如何使用PHP接受加密貨幣的支付。 一、環…

    編程 2025-04-29
  • Python爬蟲亂碼問題

    在網路爬蟲中,經常會遇到中文亂碼問題。雖然Python自帶了編碼轉換功能,但有時候會出現一些比較奇怪的情況。本文章將從多個方面對Python爬蟲亂碼問題進行詳細的闡述,並給出對應的…

    編程 2025-04-29
  • NodeJS 建立TCP連接出現粘包問題

    在TCP/IP協議中,由於TCP是面向位元組流的協議,發送方把需要傳輸的數據流按照MSS(Maximum Segment Size,最大報文段長度)來分割成若干個TCP分節,在接收端…

    編程 2025-04-29
  • 如何解決vuejs應用在nginx非根目錄下部署時訪問404的問題

    當我們使用Vue.js開發應用時,我們會發現將應用部署在nginx的非根目錄下時,訪問該應用時會出現404錯誤。這是因為Vue在刷新頁面或者直接訪問非根目錄的路由時,會認為伺服器上…

    編程 2025-04-29
  • 如何解決egalaxtouch設備未找到的問題

    egalaxtouch設備未找到問題通常出現在Windows或Linux操作系統上。如果你遇到了這個問題,不要慌張,下面我們從多個方面進行詳細闡述解決方案。 一、檢查硬體連接 首先…

    編程 2025-04-29

發表回復

登錄後才能評論