[Sun Sep 01 11:12:38 2013] [notice] child pid 1559 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:13:01 2013] [notice] child pid 1562 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:13:15 2013] [notice] child pid 1566 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:14:24 2013] [notice] child pid 1565 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:14:45 2013] [notice] child pid 15047 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:16:23 2013] [notice] child pid 14997 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:16:54 2013] [notice] child pid 1560 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:17:30 2013] [notice] child pid 15447 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:18:19 2013] [notice] child pid 15094 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:28:33 2013] [notice] child pid 1563 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:34:24 2013] [notice] child pid 1564 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
[Sun Sep 01 11:50:32 2013] [notice] child pid 1568 exit signal Segmentation fault (11), possible coredump in /tmp/httpd_coredump
Апач умирает, сайты не работают, выводится 500 ошибка. Потом через какое-то время все восстанавливается.
Использую последнюю последнюю VMBitrix4.2 на физическом сервере, объем памяти 32 Гб.
Смотрю дамп:
gdb /usr/sbin/httpd core bt
Код
(gdb) bt
#0 0x00007f1862cd58fd in do_bind_function () from /etc/httpd/modules/libphp5.so
#1 0x00007f1862d1494c in ?? () from /etc/httpd/modules/libphp5.so
#2 0x00007f1862d146f0 in execute () from /etc/httpd/modules/libphp5.so
#3 0x00007f1862ceee2d in zend_execute_scripts () from /etc/httpd/modules/libphp5.so
#4 0x00007f1862c9cf08 in php_execute_script () from /etc/httpd/modules/libphp5.so
#5 0x00007f1862d77d75 in ?? () from /etc/httpd/modules/libphp5.so
#6 0x00007f186847cbb0 in ap_run_handler ()
#7 0x00007f186848046e in ap_invoke_handler ()
#8 0x00007f186848bb30 in ap_process_request ()
#9 0x00007f18684889a8 in ?? ()
#10 0x00007f18684846b8 in ap_run_process_connection ()
#11 0x00007f1868490977 in ?? ()
#12 0x00007f1868490c8a in ?? ()
#13 0x00007f1868490fbb in ap_mpm_run ()
#14 0x00007f1868468900 in main ()
Естественно апач умер из-за PHP.
Например, я уменьшил размер recursion_limit с 14000 до 7000. Ошибка повторилась.
На странице проверки сайта иногда возникает ворнинг PHP:
Код
Warning: require_once(): Unable to allocate memory for pool. in /home/bitrix/ext_www/мой_сайт/bitrix/modules/main/admin/site_checker.php on line 255
Ворнинг временно лечится перезагрузкой апача. Пробовал увеличить apc.shm_size с 256 до 512. Ворнинг стал возникать реже но возникает.
Монитор производительности от меня еще чего-то хочет:
Код
apc.shm_size ( текущее значение:"512M" ) 100.00% используемой памяти Увеличить размер кеша.
На сервере нет еще никаких нагруженных проектов. Самый посещаемый сайт - корпортивный портал.
Какие магические действия еще можно применить?
Проверка сайта пишет:
Код
Размер стека и pcre.recursion_limit
Возможны проблемы в работе с длинными строками из-за системных ограничений
Как в скрипте запуска Apache написать: ulimit -s unlimited ? Где это скрипт и куда в нем это писать? Как смотреть coredump дальше? Как понять какое расширение глючит? Почему в VMBitrix используется 5.3.3? Почему бы её не обновить?
# Set parameters required for proper Bitrix engine functioning.
# You can redefine parameters specified in this file
# by editing /etc/php.d/z_bx_custom_settings.ini
# Configure error processing
display_errors = On
error_reporting = E_ALL & ~E_NOTICE & ~E_WARNING
# Set some more PHP parameters
enable_dl = Off
short_open_tag = On
allow_url_fopen = On
allow_call_time_pass_reference = On
# Change default values of important constants
max_input_vars = 4000
max_file_uploads = 100
max_execution_time = 300
post_max_size = 1024M
upload_max_filesize = 1024M
pcre.backtrack_limit = 1000000
;pcre.recursion_limit = 14000
pcre.recursion_limit = 3500
realpath_cache_size = 4096k
# Utf-8 support
mbstring.func_overload = 2
mbstring.internal_encoding = UTF-8
# Configure PHP sessions
session.entropy_length = 128
session.entropy_file = /dev/urandom
session.save_path = "/tmp/php_sessions/www"
# Set directory for temporary files
upload_tmp_dir = "/tmp/php_upload/www"
;sendmail_path = msmtp -t -i
sendmail_path = /usr/sbin/sendmail -t -i
date.timezone = Europe/Moscow
В целом файл таким и был, только настройки были в другом порядке и без комментариев.
У нас только пара отличий от вашего примера:
- наш сервер сам рассылает почту через postfix, - параметр pcre.recursion_limit уменьшил еще больше до 3500, чтобы исключить возможность падения из-за pcre
(gdb) bt
#0 0x00007f283dd848fd in do_bind_function ()
from /etc/httpd/modules/libphp5.so
#1 0x00007f283ddc394c in ?? () from /etc/httpd/modules/libphp5.so
#2 0x00007f283ddc36f0 in execute () from /etc/httpd/modules/libphp5.so
#3 0x00007f283dd94575 in zend_call_function ()
from /etc/httpd/modules/libphp5.so
#4 0x00007f283dcec797 in ?? () from /etc/httpd/modules/libphp5.so
#5 0x00007f283ddec3b8 in ?? () from /etc/httpd/modules/libphp5.so
#6 0x00007f283ddc36f0 in execute () from /etc/httpd/modules/libphp5.so
#7 0x00007f283dd92f6a in zend_eval_stringl ()
from /etc/httpd/modules/libphp5.so
#8 0x00007f283dc5fc8f in php_pcre_replace_impl ()
from /etc/httpd/modules/libphp5.so
#9 0x00007f283dc608a7 in ?? () from /etc/httpd/modules/libphp5.so
#10 0x00007f283dc61066 in ?? () from /etc/httpd/modules/libphp5.so
#11 0x00007f283dc61453 in ?? () from /etc/httpd/modules/libphp5.so
#12 0x00007f283ddec3b8 in ?? () from /etc/httpd/modules/libphp5.so
#13 0x00007f283ddc36f0 in execute () from /etc/httpd/modules/libphp5.so
#14 0x00007f283dd9de2d in zend_execute_scripts ()
from /etc/httpd/modules/libphp5.so
#15 0x00007f283dd4bf08 in php_execute_script ()
from /etc/httpd/modules/libphp5.so
#16 0x00007f283de26d75 in ?? () from /etc/httpd/modules/libphp5.so
То есть я не могу точно определить имя файла php и функцию php, которые вызываются. Знать бы как.
-------
Судя по access.log во время ошибок вызываются разные файлы сайта, например:
Код
"GET /bitrix/tools/public_session.php?sessid=0bcb65a867766a54360b1259bf654321&interval=0&k=be4e5dc13b0950a5e2e84c3162123456
HTTP/1.0" 200 2 "http://мой_портал/extranet/workgroups/group/42/tasks/"
"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1"
Александр Сербул в свое время написал неплохую статью на этот счет, по мотивам руководства из PHP. Если же ходить по стеку и исследовать локальные переменные желания нет, то существует способ вызвать непосредственный "родной" backtrace PHP. Подробней это описано в этой статье. Правда такой способ потребует дополнительной подготовки в виде добавления отладочной информации для PHP. В CentOS это можно сделать установив yum-utils с последующим запуском debuginfo-install <имя пакета php>. Ну, либо найти и поставить пакет вручную.
1) Скачиваем и устанавливаем отладочную информацию для PHP (ссылку для CentOS приводил выше); 2) Включаем генерацию core dump в Apache; 3) Открываем core dump в gdb; 4) Получаем вывод debug_backtrace() PHP с помощью магической команды:
Код
dump_bt executor_globals.current_execute_data
Другой вариант:
Код
zbacktrace
Работает также — показывает backtrace скриптов PHP до момента падения, но смотрится менее эффектно.
Способ проверенный и неоднократно применялся в боевых условиях.
Иван пишет: Статью всегда можно найти в архиве Интернета.
Короткий пересказ:
1) Скачиваем и устанавливаем отладочную информацию для PHP (ссылку для CentOS приводил выше); 2) Включаем генерацию core dump в Apache; 3) Открываем core dump в gdb; 4) Получаем вывод debug_backtrace() PHP с помощью магической команды:
Код
dump_bt executor_globals.current_execute_data
Регулярно появляется такая же ошибка в логе апача. Но в ответ на команду dump_bt executor_globals.current_execute_data в gdb пусто.
Разве не должен быть собран php с ключем --enable-debug? На виртуальной машине Битрикс php собран как раз с ключом '--disable-debug'.
Специально развернул чистую виртуальную машину Битрикс, обеспечил падение PHP (с помощью глубокой рекурсии) и провел анализ core dump как это описано в статье. Результат.
Рекомендую еще раз, очень внимательно, выполнить все шаги, описанные в статье.
Есть подзрение что апач падает не из-за PHP. В этой статье описывается поиск причин падения апача, но в моем дампе нету функции execute.
Код
(gdb) bt
#0 0x408dfe62 in zval_mark_grey (pz=<value optimized out>) at /usr/src/debug/php-5.3.3/Zend/zend_gc.c:372
#1 0x408e08b5 in gc_mark_roots () at /usr/src/debug/php-5.3.3/Zend/zend_gc.c:433
#2 gc_collect_cycles () at /usr/src/debug/php-5.3.3/Zend/zend_gc.c:660
#3 0x408c1fc5 in zend_deactivate () at /usr/src/debug/php-5.3.3/Zend/zend.c:900
#4 0x40868dc8 in php_request_shutdown (dummy=0x0) at /usr/src/debug/php-5.3.3/main/main.c:1634
#5 0x409508e4 in php_apache_request_dtor (r=0x520417d0) at /usr/src/debug/php-5.3.3/sapi/apache2handler/sapi_apache2.c:509
#6 php_handler (r=0x520417d0) at /usr/src/debug/php-5.3.3/sapi/apache2handler/sapi_apache2.c:681
#7 0x400266a1 in ap_run_handler (r=0x520417d0) at /usr/src/debug/httpd-2.2.15/server/config.c:158
#8 0x4002a426 in ap_invoke_handler (r=0x520417d0) at /usr/src/debug/httpd-2.2.15/server/config.c:376
#9 0x400371a8 in ap_process_request (r=0x520417d0) at /usr/src/debug/httpd-2.2.15/modules/http/http_request.c:282
#10 0x40033c98 in ap_process_http_connection (c=0x410bc878) at /usr/src/debug/httpd-2.2.15/modules/http/http_core.c:190
#11 0x4002ef11 in ap_run_process_connection (c=0x410bc878) at /usr/src/debug/httpd-2.2.15/server/connection.c:43
#12 0x4003caea in child_main (child_num_arg=<value optimized out>) at /usr/src/debug/httpd-2.2.15/server/mpm/prefork/prefork.c:667
#13 0x4003ce7e in make_child (s=<value optimized out>, slot=0) at /usr/src/debug/httpd-2.2.15/server/mpm/prefork/prefork.c:763
#14 0x4003de53 in perform_idle_server_maintenance (_pconf=0x4052c0a8, plog=0x4055a160, s=0x4052dfa0)
at /usr/src/debug/httpd-2.2.15/server/mpm/prefork/prefork.c:898
#15 ap_mpm_run (_pconf=0x4052c0a8, plog=0x4055a160, s=0x4052dfa0) at /usr/src/debug/httpd-2.2.15/server/mpm/prefork/prefork.c:1102
#16 0x40010ad2 in main (argc=1, argv=0xbfdb2804) at /usr/src/debug/httpd-2.2.15/server/main.c:760
Это очень похоже на старую проблему со сборщиком мусора в PHP. Проблема тянется уже очень давно, как минимум с версии PHP 5.2, и фикс был предложен только сейчас, для версии 5.5. Чтобы дать какие-то рекомендации, необходимо больше информации. Если есть возможность, прошу выполнить следующие команды и выложить содержимое файла /tmp/sys_info, например, в pastebin:
Код
OUT="/tmp/sys_info"
uname -a >> "$OUT"
yum list httpd | grep -vE "(Load|\*)" >> "$OUT"
yum list php | grep -vE "(Load|\*)" >> "$OUT"
yum list php-debuginfo | grep -vE "(Load|\*)" >> "$OUT"
cout() { find $1 -type f -iname "$2" | while read i; do printf "\n\n$i\n" >> "$OUT"; cat "$i" >> "$OUT"; done; }
cout /etc/httpd/ "*.conf"
cout /etc/php.d/ "*.ini"
cout /etc/ "php.ini"
Если в конфигурационных файлах Apache или PHP указаны какие-нибудь пароли, IP адреса или иная частная информация, необходимо удалить ее из /tmp/sys_info.
Иван пишет: Это очень похоже на старую проблему со сборщиком мусора в PHP. Проблема тянется уже очень давно, как минимум с версии PHP 5.2, и фикс был предложен только сейчас, для версии 5.5. Чтобы дать какие-то рекомендации, необходимо больше информации. Если есть возможность, прошу выполнить следующие команды и выложить содержимое файла /tmp/sys_info, например, в pastebin :
Код
OUT="/tmp/sys_info"
uname -a >> "$OUT"
yum list httpd | grep -vE "(Load|\*)" >> "$OUT"
yum list php | grep -vE "(Load|\*)" >> "$OUT"
yum list php-debuginfo | grep -vE "(Load|\*)" >> "$OUT"
cout() { find $1 -type f -iname "$2" | while read i; do printf "\n\n$i\n" >> "$OUT"; cat "$i" >> "$OUT"; done; }
cout /etc/httpd/ "*.conf"
cout /etc/php.d/ "*.ini"
cout /etc/ "php.ini"
Если в конфигурационных файлах Apache или PHP указаны какие-нибудь пароли, IP адреса или иная частная информация, необходимо удалить ее из /tmp/sys_info.
Спасибо, стало гораздо проще. Теперь прошу создать в рамках сайта файл test.php (название произвольное) со следующим содержимым:
Код
<?php
class A {
public $c;
public function segfault() {
$GLOBALS['a']->get()->e = true;
$this->c = new B();
$this->c->d[] = true;
}
public function get() {
return $this->c;
}
}
class B {}
$a = new A();
$a->segfault();
Затем, обратиться к файлу через браузер. Интересует следующее:
1) Случится ли Segmentation fault; 2) Если да, то будет ли backtrace соответствовать приведенному в комментарии #17.
Как и ожидалось, ошибка сборщика мусора. Исправление было сделано недавно и лишь для версии PHP 5.6 alpha. В данном случае есть два пути решения:
1) Простой и относительно быстрый.
Для воспроизведения ошибки нужны довольно-таки необычные условия. Замена хотя бы одной строчки из примера выше приводит к работающему коду. Это значит, что если чуть-чуть поменять проблемный код на сайте, ошибка перестанет себя проявлять.
Для того чтобы найти проблемный код, нужно обратиться к логу Nginx. В частности, необходимо найти все ссылки, для которых Apache возвратил код 502 и попробовать пройти по этим ссылкам. Если это действие приведет к Segmentation fault, необходимо последовательно комментировать участки кода вне ядра Битрикс (см. далее), пока Segmentation fault не перестанет происходить. Как только нужный участок кода будет найдет, необходимо переписать его другим образом.
Сомнительно, что проблемный код расположен в ядре Битрикс: эта ошибка PHP присутствует во всех версиях PHP и на всех платформах. В частности, я тестировал на: 5.3.10-1 x64, Ubuntu, 5.4.9-4 x64, Ubuntu, 5.3.3-27 i686, CentOS, 5.3.3-22 x64, CentOS. Если бы проблема таилась лишь в коде Битрикс, ее давно бы уже заметили.
Плюсы такого подхода: можно решить проблему достаточно быстро.
Минусы такого подхода: настоящая проблема (ошибка в интерпретаторе PHP) не решается, потому проблема может проявить себя снова (хотя шансы и невелики).
2) Для сильных духом.
Заключается в том, чтобы разобрать rpm-пакет, сделать патч с исправлением для исходного кода PHP. Пересобрать rpm-пакет и заменить существующую версию PHP на исправленную. При этом, так как все будет сделано через rpm, возможность обновления PHP штатными средствами операционной системы не потеряются.
Плюсы такого подхода: устраняется именно причина проблемы — ошибка в интерпретаторе PHP.
Минусы такого подхода: после каждого обновления PHP патч придется делать заново, иначе проблема вернется. То есть, придется следить за обновлениями. Кроме того, выполнение всех необходимых действий займет довольно много времени: нужно будет поднимать еще одну виртуальную машину (желательно), перекомпилировать PHP, возиться с rpm и так далее.
Описание второго пути потребует довольно много времени, потому, смогу написать инструкцию только если этот подход точно будет выбран (свободного времени катастрофически не хватает, не хотелось бы его терять).
P.S. Сделал исправленный rpm-пакет для текущей версии виртуальной машины Битрикс. Но там php-5.3.3-27, для вашего случая не подойдет.
Возможно после перехода на VMBitrix 4.3 решусь и на второй
Если правильно понял второй способ, нужно сделать патч для php, пересобрать можно так А вот что поправить в исходниках php? Если можно выложите кусок кода или хотя бы примерно где искать.
Относительно первого метода, я так понял нужно анализировать error-лог ngnix. Но в нем в основном ошибки что не найден файл вида /home/bitrix/mysite/bitrix/main.post.form/templates.default/images/spoiler.png
На файл с приведенным выше скриптом ngnix записал ошибку закрытия подключения апача.
Не могу понять что как узнать что вернул апач ngnix.