2011-06-13 23 views
2

我們有一個帶有7GB內存的64位Web服務器,PHP在週末運行我們的網站,該網站由Codeigniter支持,並具有選擇性的Zend類。幾乎所有到我們網站的PHP請求都會導致SIGSEGV。我們的其他服務器在運行該站點的相同規格上的數量遠遠少於這些。不確定是否相關,我們在APC上運行(PHP 5.3.6版本,我認爲它是3.1.3p1),我們發現我們有很多「無法爲池分配內存」。在錯誤日誌中。運行APC統計我發現緩存已滿。PHP 5.3.6 SIGSEGV(帶有Zend_Locale?)

所以我的第一個問題,我認爲有一個完整的APC緩存不應該導致SIGSEGV?

這是PHP 5.3.6作爲標題和gdb它,我想出了下面的回溯:

 
Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x7f9d259007e0 (LWP 6020)] 
strlen() at ../sysdeps/x86_64/strlen.S:31 
31    pcmpeqb (%rdi), %xmm2 
(gdb) backtrace 
#0 strlen() at ../sysdeps/x86_64/strlen.S:31 
#1 0x00007f9d1e14e274 in xbuf_format_converter (xbuf=0x7fffa8560f10, fmt=0x7f9d1e26d0df "s, %s%s given, called in %s on line %d and defined", ap=0x7fffa8560fb0) 
    at /usr/src/debug/php-5.3.6/main/spprintf.c:574 
#2 0x00007f9d1e14f164 in vspprintf (pbuf=0x7f9d270327d8, max_len=0, format=, ap=) at /usr/src/debug/php-5.3.6/main/spprintf.c:797 
#3 0x00007f9d1e19b56f in zend_error (type=4096, format=0x7f9d1e26d0b8 "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined") 
    at /usr/src/debug/php-5.3.6/Zend/zend.c:1051 
#4 0x00007f9d1e1eac56 in zend_verify_arg_error (execute_data=0x7f9d257e88f8) at /usr/src/debug/php-5.3.6/Zend/zend_execute.c:471 
#5 zend_verify_arg_type (execute_data=0x7f9d257e88f8) at /usr/src/debug/php-5.3.6/Zend/zend_execute.c:505 
#6 ZEND_RECV_SPEC_HANDLER (execute_data=0x7f9d257e88f8) at /usr/src/debug/php-5.3.6/Zend/zend_vm_execute.h:449 
#7 0x00007f9d1e1c0e30 in execute (op_array=0x7f9d26ffe998) at /usr/src/debug/php-5.3.6/Zend/zend_vm_execute.h:107 
#8 0x00007f9d1e19b0fd in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/debug/php-5.3.6/Zend/zend.c:1194 
#9 0x00007f9d1e1487c8 in php_execute_script (primary_file=0x7fffa8563640) at /usr/src/debug/php-5.3.6/main/main.c:2268 
#10 0x00007f9d1e2246a5 in php_handler (r=0x7f9d26dbc8c0) at /usr/src/debug/php-5.3.6/sapi/apache2handler/sapi_apache2.c:669 
#11 0x00007f9d2593d8b0 in ap_run_handler (r=0x7f9d26dbc8c0) at /usr/src/debug/httpd-2.2.16/server/config.c:158 
#12 0x00007f9d2594116e in ap_invoke_handler (r=0x7f9d26dbc8c0) at /usr/src/debug/httpd-2.2.16/server/config.c:376 
#13 0x00007f9d2594c5fc in ap_internal_redirect (new_uri=, r=) at /usr/src/debug/httpd-2.2.16/modules/http/http_request.c:502 
#14 0x00007f9d1f3637a5 in handler_redirect (r=0x7f9d26dcad38) at /usr/src/debug/httpd-2.2.16/modules/mappers/mod_rewrite.c:4831 
#15 0x00007f9d2593d8b0 in ap_run_handler (r=0x7f9d26dcad38) at /usr/src/debug/httpd-2.2.16/server/config.c:158 
#16 0x00007f9d2594116e in ap_invoke_handler (r=0x7f9d26dcad38) at /usr/src/debug/httpd-2.2.16/server/config.c:376 
#17 0x00007f9d2594c7c0 in ap_process_request (r=0x7f9d26dcad38) at /usr/src/debug/httpd-2.2.16/modules/http/http_request.c:282 
#18 0x00007f9d25949698 in ap_process_http_connection (c=0x7f9d26dabf78) at /usr/src/debug/httpd-2.2.16/modules/http/http_core.c:190 
#19 0x00007f9d259453c8 in ap_run_process_connection (c=0x7f9d26dabf78) at /usr/src/debug/httpd-2.2.16/server/connection.c:43 
#20 0x00007f9d259510b7 in child_main (child_num_arg=) at /usr/src/debug/httpd-2.2.16/server/mpm/prefork/prefork.c:662 
#21 0x00007f9d259513ca in make_child (s=0x7f9d268a8860, slot=17) at /usr/src/debug/httpd-2.2.16/server/mpm/prefork/prefork.c:758 
#22 0x00007f9d2595204c in perform_idle_server_maintenance (_pconf=, plog=, s=) at /usr/src/debug/httpd-2.2.16/server/mpm/prefork/prefork.c:893 
#23 ap_mpm_run (_pconf=, plog=, s=) at /usr/src/debug/httpd-2.2.16/server/mpm/prefork/prefork.c:1097 
#24 0x00007f9d25929840 in main (argc=1, argv=0x7fffa8563c88) at /usr/src/debug/httpd-2.2.16/server/main.c:740 

通過一些簡單的GDB我發現執行似乎已經達到從Zend_Locale :: _ prepareLocale()和明顯,而PHP試圖輸出錯誤消息一些壞指針導致SIGSEGV:

 
(gdb) frame 9 
#9 0x00007f9d1e1487c8 in php_execute_script (primary_file=0x7fffa8563640) at /usr/src/debug/php-5.3.6/main/main.c:2268 
2268     retval = (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS); 
(gdb) p *primary_file 
$1 = {type = ZEND_HANDLE_FILENAME, filename = 0x7f9d26dcd2d0 "/mnt/goserver/goanimate.com/index.php", opened_path = 0x0, handle = {fd = 646922536, fp = 0x7f9d268f4128, stream = {handle = 0x7f9d268f4128, 
     isatty = 0, mmap = {len = 140312938585584, pos = 140312938463096, map = 0x7f9d26dca068, buf = 0x7f9d26dabff8 "\310\307\332&\235\177", old_handle = 0x7f9d25948971, old_closer = 0}, reader = 0xc, 
     fsizer = 0x7f9d26dc3840, closer = 0x7f9d26dca078}}, free_filename = 0 '\000'} 
(gdb) frame 7 
#7 0x00007f9d1e1c0e30 in execute (op_array=0x7f9d27000c40) at /usr/src/debug/php-5.3.6/Zend/zend_vm_execute.h:107 
107      if ((ret = EX(opline)->handler(execute_data TSRMLS_CC)) > 0) { 
(gdb) p *op_array 
$2 = {type = 2 '\002', function_name = 0x7f9d0ef9aec0 "_prepareLocale", scope = 0x7f9d26ffd228, fn_flags = 1025, prototype = 0x0, num_args = 2, required_num_args = 1, arg_info = 0x7f9d0ef9ae68, 
    pass_rest_by_reference = 0 '\000', return_reference = 0 '\000', done_pass_two = 1 '\001', refcount = 0x7f9d27000d38, opcodes = 0x7f9d0efad760, last = 161, size = 161, vars = 0x7f9d0efb2540, 
    last_var = 12, size_var = 16, T = 94, brk_cont_array = 0x7f9d0efb2530, last_brk_cont = 1, current_brk_cont = -1, try_catch_array = 0x0, last_try_catch = 0, static_variables = 0x0, start_op = 0x0, 
    backpatch_count = 0, this_var = 4294967295, filename = 0x7f9d0ef9aed0 "/mnt/goserver/gslib/include/Zend/Locale.php", line_start = 1003, line_end = 1069, 
    doc_comment = 0x7f9d0ef9af08 "/**\n  * Internal function, returns a single locale on detection\n  *\n  * @param string|Zend_Locale $locale (Optional) Locale to work on\n  * @param boolean", ' ' , "$strict (Optional) St"..., doc_comment_len = 362, early_binding = 4294967295, reserved = {0x1, 0x0, 0x0, 0x0}} 
(gdb) p op_array->arg_info 
$3 = (zend_arg_info *) 0x7f9d0ef9ae68 
(gdb) p *(op_array->arg_info) 
$4 = {name = 0x7f9d0ef9c3b0 "locale", name_len = 6, class_name = 0xffffffff , class_name_len = 0, array_type_hint = 0 '\000', allow_null = 1 '\001', 
    pass_by_reference = 0 '\000', return_reference = 0 '\000', required_num_args = 0} 
(gdb) frame 2 
#2 0x00007f9d1e14f164 in vspprintf (pbuf=0x7f9d27034a98, max_len=0, format=, ap=) at /usr/src/debug/php-5.3.6/main/spprintf.c:797 
797    xbuf_format_converter(&xbuf, format, ap); 
(gdb) frame 1 
#1 0x00007f9d1e14e274 in xbuf_format_converter (xbuf=0x7fffa8560f10, fmt=0x7f9d1e26d0df "s, %s%s given, called in %s on line %d and defined", ap=0x7fffa8560fb0) 
    at /usr/src/debug/php-5.3.6/main/spprintf.c:574 
574                s_len = strlen(s); 
(gdb) p s 
$7 = 0xffffffff 

我在考慮失敗mallocs或者被留在了Zend引擎的代碼被忽視,但我不知道足夠的像Zend內部來確認它。任何人都有這方面的線索?謝謝。

+1

你可能想問一下關於EFNet上的php.pecl – Gordon 2011-06-13 08:32:52

回答

0

我不是C程序員,知道PHP解釋器/ Zend引擎背後的源代碼。但是我遵循Zend_Locale :: _ prepareLocale()方法,並且在你指定的調試數據中,我正在調用strlen()導致溢出。我在想:

C中的strlen()調用是從字符串相關的PHP函數調用中翻譯而來的。在提到的Zend_Locale方法中,我看到了這些可能相關的PHP函數:explode(),strstr(),strlen()。

通過檢查Zend_Local :: _ prepareLocale(),您可以發現傳遞給字符串函數的數據是$ local變量。由於此語言環境是由不同的資源(環境變量,用戶瀏覽器指定的數據等)構建的,因此此值可能會導致內存故障。如果你能找出導致它的PHP程序的狀態,調試可能會更容易。可能會編輯Zend_Locale的源代碼,並在某些行上打印出$ locale變量以進行逐行調試。