6

我一直在使用以下方法编写网站:

  1. Zend Framework 1.11.5(完整的 MVC)
  2. PHP 5.3.6
  3. 阿帕奇 2.2.19
  4. VPS 上的 CentOS 5.6 i686 virtuozzo
  5. cPanel WHM 11.30.1(构建 4)
  6. mysql 5.1.56-日志
  7. mysqli API 5.1.56

突然对mysql做了一些“SHOW CREATE TABLE”查询,我明白了。

[Wed Jul 20 17:35:23 2011
] [notice] EACCELERATOR(5827): PHP crashed on opline 138 of fetch_fields() at /usr/lib/php/Zend/Db/Statement/Mysqli.php:235

我试过禁用加速器但没有成功

[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
[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

有问题的行是:$row = $db->fetchRow("SHOW CREATE TABLE 222AFI");。如果我在它执行之前返回,一切都会好起来的。$db 是 Zend_Db_Adapter_Mysqli 的实例。最糟糕的部分是它不是确定性的。该程序有时可以通过,而另一些则不能。通常它不会在不崩溃 php 的情况下通过该行。

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

我没有写信给 internals@lists.php.net 因为我没有https://bugs.php.net/bugs-generating-backtrace.php。这可能很愚蠢,但我尝试使用“--enable-debug”重新编译 apache,(这是一个生产服务器)。但是“PHP Apache 模块:运行 httpd -X,并访问使 PHP 崩溃的脚本”是我无法工作的部分。服务器告诉我端口 80 已被使用。

谁能给我一些建议?如果我在做一些疯狂的事情,至少还有其他选择?

我可以尝试在午夜重新编译 apache,但很高兴知道我不会破坏任何东西。你如何看待这对我来说非常重要。

编辑

我必须用 --enable-debug 编译 php。这很奇怪,它没有像通常那样崩溃。这很难,20 次尝试中可能有一次崩溃。如果用 -X 启动 apache,就更难让 php 崩溃,因为 httpd 响应时间太长。

编辑2

即使在 20 次尝试之后,如果我在没有 -X 标志的情况下启动 httpd,我也可以让它崩溃。但是我模拟了一个初始化 $_SERVER 变量的脚本,以使 Zend 相信它是通过浏览器调用的。当我用“php crash.php”多次(如50次)执行此脚本时,一切正常。我开始相信它与 php 重用进程有关。我正在使用 mod_fcgi 运行 apache,并且:

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"
4

5 回答 5

2

请看一下https://bugs.php.net/bug.php?id=55414,终于有人接受了。部分解决方案比我的实施得更好。

于 2011-08-16T16:06:02.797 回答
0

首先尝试编写一个重现问题的最小示例,即不使用 Zend 框架、Apache 等。只需一个 10 行左右的脚本来设置数据库连接并发出查询。

于 2011-07-21T13:41:38.540 回答
0

您可以在服务器上运行 phpinfo() 并发布 thread_safety 的结果吗?如果你的 apache 不是线程安全的,那么 php 应该以同样的方式编译。

于 2011-07-21T13:37:49.940 回答
0

我找到了一个临时解决方案。这很丑陋,但适合:

public function 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;
}

您需要将 $this->_config 替换为真实的连接数组。

该脚本运行任何返回行的 SQL 命令。现在是我正在采取的解决方案。如果有人希望主动帮助我,我仍然有消息来源。我也是使用 PHPUnit 和 Zend(确定性地)出现 PHP 段错误的人。我在我的工作中做这一切,没有资源来测试它。感谢您的理解。

于 2011-07-25T18:21:13.700 回答
0

这里的一个建议帮助修复了我正在处理的 Web 服务的分段错误:

http://kb.zend.com/index.php?View=entry&EntryID=436

“解决方法是在 php.ini 中为参数 'date.timezone' 设置一个值。例如:

date.timezone = "America/New_York" 此处提供支持的时区列表 - www.php.net/manual/en/timezones.php"

于 2011-08-17T14:48:46.477 回答