PHP崩溃(seg-fault)在mod_fcgi下,apache

我一直在编程一个网站使用:

  1. Zend Framework 1.11.5(完整的MVC)
  2. PHP 5.3.6
  3. Apache 2.2.19
  4. CentOS 5.6 i686 virtuozzo on vps
  5. cPanel WHM 11.30.1(build 4)
  6. Mysql 5.1.56-log
  7. Mysqli API 5.1.56

这个问题从这里开始https://stackoverflow.com/questions/6769515/php-programming-seg-fault 。 简而言之,PHP给了我随机的分割错误。

[Wed Jul 20 17:45:34 2011] [error] mod_fcgid: process /usr/local/cpanel/cgi-sys/php5(11562) exit(communication error), get unexpected signal 11 [Wed Jul 20 17:45:34 2011] [warn] [client 190.78.208.30] (104)Connection reset by peer: mod_fcgid: error reading data from FastCGI server [Wed Jul 20 17:45:34 2011] [error] [client 190.78.208.30] Premature end of script headers: index.php 

关于扩展。 当我用“–enable-debug”标志编译php时,我必须禁用这一行:

 zend_extension="/usr/local/IonCube/ioncube_loader_lin_5.3.so" 

否则,服务器不接受请求,我得到一个“与服务器的连接被重置”。 由于相同的原因,我可能也必须禁用eaccelerator。 我仍然不明白为什么Apache会运行一些,而有些则不是。

 extension="eaccelerator.so" 

无论如何,我得到httpd运行后,seg-fault可以随机发生。 如果我不用“–enable-debug”标志编译php,我可以得到确定一个PHP崩溃:

 <?php class Admin_DbController extends Controller_BaseController { public function updateSqlDefinitionsAction() { $db = Zend_Registry::get('db'); $row = $db->fetchRow("SHOW CREATE TABLE 222AFI"); } } ?> 

但是,如果我用“–enable-debug”标志编译php,真的很难得到这个错误。 我必须增加一些复杂性才能使其崩溃。 我必须做很多平行的请求几秒钟才能崩溃:

 <?php class Admin_DbController extends Controller_BaseController { public function updateSqlDefinitionsAction() { $db = Zend_Registry::get('db'); $tableList = $db->listTables(); foreach ($tableList as $tableName){ $row = $db->fetchRow("SHOW CREATE TABLE " . $db->quoteIdentifier($tableName)); file_put_contents( DB_DEFINITIONS_PATH . '/' . $tableName . '.sql', $row['Create Table'] . ';' ); } } } ?> 

请注意这是相同的脚本,但是为数据库中的所有表创buildDDL而不是一个。 看来,如果PHP是沉重的负载(扩展名和我做很多并行请求),这是当我得到PHP崩溃。


关于用“-X”启动httpd:我试过了。 事情是,用–enable-debug已经很难让php崩溃了。 使用“-X”选项(只启用一个subprocess),我不能做并行请求。 所以我一直没有能够创build适当的debuggingbacktrace: https : //bugs.php.net/bugs-generating-backtrace.php

我的具体问题是,我该怎么做一个coredump?


 root@GWT4 [~]# httpd -V Server version: Apache/2.2.19 (Unix) Server built: Jul 20 2011 19:18:58 Cpanel::Easy::Apache v3.4.2 rev9999 Server's Module Magic Number: 20051115:28 Server loaded: APR 1.4.5, APR-Util 1.3.12 Compiled using: APR 1.4.5, APR-Util 1.3.12 Architecture: 32-bit Server MPM: Prefork threaded: no forked: yes (variable process count) Server compiled with.... -D APACHE_MPM_DIR="server/mpm/prefork" -D APR_HAS_SENDFILE -D APR_HAS_MMAP -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) -D APR_USE_SYSVSEM_SERIALIZE -D APR_USE_PTHREAD_SERIALIZE -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT -D APR_HAS_OTHER_CHILD -D AP_HAVE_RELIABLE_PIPED_LOGS -D DYNAMIC_MODULE_LIMIT=128 -D HTTPD_ROOT="/usr/local/apache" -D SUEXEC_BIN="/usr/local/apache/bin/suexec" -D DEFAULT_PIDLOG="logs/httpd.pid" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_LOCKFILE="logs/accept.lock" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="conf/mime.types" -D SERVER_CONFIG_FILE="conf/httpd.conf" 

获取核心转储包括将“核心文件大小” rlimit设置为您要从中获取核心转储的进程的非零值。 鉴于您在FCGI中运行PHP,您并不真正关心Apache本身,它不是简单的。 你想有一个脚本来运行ulimit -c unlimited然后执行你的FCGI服务器。

我喜欢为核心提供一个单独的scratch分区,所以如果它们有点大或者/proc/sys/kernel/core_pattern的话,就不会在其他地方引起磁盘填充问题 – set /proc/sys/kernel/core_pattern类似于/var/cores/%e-%p.core

你必须使用ioncube_loader和eaccelerator? 对于eaccelerator来说,他们的5.3.x支持最多只有几个点,大多数5.3用户依赖于APC(无论如何FCGI也能更好地工作)。

如果你必须使用eaccelerator,你是否在做一个“distclean”,然后他们站在INSTALL指令(仔细检查你正在加载的phpize是5.3.6,而不是以前安装的一些剩余部分)? 我怀疑这就是你的核心的全部来源,Apache并不是罪魁祸首。

我find了一个临时解决scheme 这是丑陋的,但适合:

公共职能selectCmd($ q){

 $charsFrom = array("\\a", "\\t", "\\n", "\\v", "\\f", "\\r", "\\\\", "\\0", "\\\"", "\\\'", "\\b"); $charsTo = array("\a", "\t", "\n", "\v", "\f", "\r", "\\", "\0", "\"", "\'", "\b"); exec('echo ' . escapeshellarg($q) . ' | mysql' . ' -h ' . escapeshellarg($this->_config['host']). ' -u ' . escapeshellarg($this->_config['username']). ' -p' . escapeshellarg($this->_config['password']). ' ' . escapeshellarg($this->_config['dbname']), $output); $colNames = explode("\t", array_shift($output)); foreach ($colNames as &$colName){ $colName = str_replace($charsFrom, $charsTo, $colName); } unset($colName); $rowSet = array(); foreach ($output as $line){ $row = array(); $rawRow = explode("\t", $line); for ($i = 0; $i < count($rawRow); ++ $i){ $row[$colNames[$i]] = str_replace($charsFrom, $charsTo, $rawRow[$i]); } $rowSet[] = $row; } return $rowSet; 

}

你需要用一个真正的连接数组replace$ this – > _ config。

这个脚本运行任何返回行的SQL命令。 现在是我正在采取的解决scheme。 如果有人希望主动帮助我,我仍然有来源。 我也是使用PHPUnit和Zend(确定性)的PHP seg-fault。 我在工作中正在做这一切,没有足够的资源来testing它。 感谢您的理解。

不知道在这种情况下是否有帮助,但我只设置了一个孩子,findPID,然后用strace进行debugging

 strace -p PID