Ошибка программирования PHP - PullRequest
6 голосов
/ 21 июля 2011

Я программировал сайт, используя:

  1. Zend Framework 1.11.5 (полная MVC)
  2. PHP 5.3.6
  3. Apache 2.2.19
  4. CentOS 5.6 i686 virtuozzo на vps
  5. cPanel WHM 11.30.1 (сборка 4)
  6. Mysql 5.1.56-log
  7. Mysqli API 5.1.56

Внезапно выполняя несколько запросов "SHOW CREATE TABLE" к mysql, я получил это.

[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

Я попытался отключить eaccelerator без успеха

[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. Это может быть глупо, но я попытался перекомпилировать apache с "--enable-debug", (это рабочий сервер).Однако "PHP Apache Module: Запустите httpd -X и получите доступ к скрипту, который приводит к сбою PHP" - это часть, с которой я не работаю.Сервер сообщает, что порт 80 уже используется.

Кто-нибудь может дать мне совет?Если я делаю что-то безумное, хотя бы какие-нибудь другие варианты?

Я могу попытаться перекомпилировать apache в полночь, но было бы здорово знать, что я ничего не сломаю.То, как вы видите, это очень важно для меня.

EDIT :

Я должен скомпилировать php с помощью --enable-debug.Это странно, это не сбой, как обычно.Это сложно, из 20 попыток может быть одна сбой.А если запустить apache с ключом -X, получить сбои php будет еще труднее, потому что httpd слишком долго реагирует.

EDIT2 :

Даже если после 20 попыток,я могу сделать его сбой, если я запускаю httpd без флага -X.Однако я эмулировал скрипт, который инициализирует переменные $ _SERVER, чтобы Zend поверил, что он вызывается через браузер.Когда я выполняю этот скрипт с «php crash.php» много раз (например, 50), все идет нормально.Я начинаю верить, что это как-то связано с повторно используемыми процессами php.Я использую Apache с mod_fcgi и:

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"

Ответы [ 5 ]

2 голосов
/ 16 августа 2011

пожалуйста, взгляните на https://bugs.php.net/bug.php?id=55414,, кто-то наконец получил это.Частичное решение лучше, чем у меня.

0 голосов
/ 17 августа 2011

Это предложение помогло исправить мою ошибку сегментации для веб-службы, с которой я имел дело:

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

"Обходной путь - установить значение для параметра date.timezone'в php.ini. Например:

date.timezone = "America / New_York" Список поддерживаемых часовых поясов доступен здесь - www.php.net/manual/en/timezones.php"

.
0 голосов
/ 21 июля 2011

Сначала попробуйте написать минимальный пример, который воспроизводит проблему, то есть без использования Zend Framework, Apache и т. Д. Всего лишь 10-строчный скрипт, который устанавливает соединение с базой данных и выдает запрос.

0 голосов
/ 25 июля 2011

Я нашел временное решение. Это некрасиво, но подходит:

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, которая возвращает строки. Пока это решение, которое я принимаю. Если кто-то хочет мне активно помочь, у меня все еще есть источники. Я также парень, который имеет ошибку сегмента PHP, используя PHPUnit с Zend (детерминистически). Я делаю все это в своей работе, не имею ресурсов, чтобы проверить это. Спасибо за ваше понимание.

0 голосов
/ 21 июля 2011

вы можете запустить phpinfo () на сервере и опубликовать результат для thread_safety? если ваш apache не безопасен для потоков, то php должен быть скомпилирован таким же образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...