Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2009.12.06;
Скачать: [xml.tar.bz2];

Вниз

PHP: error_reporting() возвращает непредвиденно ноль   Найти похожие ветки 

 
Piter ©   (2009-10-08 20:40) [0]

Некий движок написанный на PHP, есть переопределение возврата ошибок:

set_error_handler(array($Error, "general"));

Метод general:


...
public function general($errno, $errmsg, $filename, $linenum, $vars)
   {
       $this->addStack($errno, $errmsg, $filename, $linenum);
       $this->display();
   }

private function addStack($errno, $errmsg, $filename, $linenum)
   {
       $this->stack[] = array($errno, $errmsg, $filename, $linenum);
   }

public function display($error_reporting = NULL)
   {
     if (!isset($error_reporting))
       {
           $error_reporting = error_reporting(); // ВОТ ЗДЕСЬ ПРОВЕРКА error_reporting()
       }
      .............


Не удивляйтесь некоей нелогичности, это в тестовых целях.
Итак, функция error_reporting() как и положено возвращает E_ALL, то что стоит в опциях PHP.ini. До определенного момента (((

Используется PEAR, в частности подключается PEAR/DB.php, в проекте есть код:

$DB = DB::connect("строка коннекта");, DB - это класс из PEAR

До выполнения этой строки error_reporting() из метода display возвращал E_ALL в случае ошибки. Последнее полученное сообщение, когда error_reporting() еще возвращал E_ALL было:

>Runtime Notice: Non-static method DB::parseDSN() should not be called statically in file D:\Program Files\Apache\Apache\htdocs\includes\PEAR\DB.php on line 358

При получении следующего сообщения:

>Runtime Notice: Assigning the return value of new by reference is deprecated in file D:\Program Files\Apache\Apache\htdocs\includes\PEAR\DB\common.php on line 958

В функции display уже error_reporting() возвращает ноль. При этом, поиск по PEAR не дает наличие ни в одном модуле строки "error_reporting"...

Почему же значение может меняться?! Его можно поменять функцией, отличной от error_reporting(val)?!


 
McSimm ©   (2009-10-08 20:54) [1]


>
> В функции display уже error_reporting() возвращает ноль.
>

как проверял ?


 
McSimm ©   (2009-10-08 20:56) [2]

Я к тому, что вероятно заход в обрабочик был по экранированной ошибке
@ statement


 
McSimm ©   (2009-10-08 21:00) [3]

Вот код, воспроизводит это:

set_error_handler("myErrorHandler");
error_reporting(E_ALL);

@$a = $b;

function myErrorHandler($errno, $errstr, $errfile, $errline)
{
   $e = error_reporting();
   var_dump($e);
}



 
Piter ©   (2009-10-08 21:07) [4]

McSimm ©   (08.10.09 20:54) [1]
как проверял ?


добавил строчку:

echo error_reporting();

и увидел 0

McSimm ©   (08.10.09 21:00) [3]
Вот код, воспроизводит это


выдало: int(0)

Но я не понял про "по экранированной ошибке"... Как это?


 
Piter ©   (2009-10-08 21:07) [5]

McSimm ©   (08.10.09 20:56) [2]
@ statement


а, все, понял


 
Piter ©   (2009-10-08 21:11) [6]

но как-то бредово... Получается, экранирование ошибки приводит к тому, что обработчик все таки вызывается, но при этом error_reporting устанавливается в 0?!

Очень похоже на костыли какие-то... Уж лучше бы каким-нибудь аргуметом передавался флаг - надо ли экранировать ошибку...

А как-нибудь побороть можно? Например, узнать истинное значение error_reporting... Ну которое в PHP.ini по идее стоит.


 
McSimm ©   (2009-10-08 21:15) [7]


> которое в PHP.ini

ini_get() ?


 
Piter ©   (2009-10-08 21:22) [8]

ты не поверишь, но ini_get("error_reporting") - тоже начинает возвращать 0! (((


 
McSimm ©   (2009-10-08 21:24) [9]

это они напрасно :)


 
Piter ©   (2009-10-08 21:24) [10]

кстати, из твоего примера это тоже следует:

set_error_handler("myErrorHandler");
error_reporting(E_ALL);

@$a = $b;

function myErrorHandler($errno, $errstr, $errfile, $errline)
{
  $e = ini_get("error_reporting");
  var_dump($e);
}


Результат: string(1) "0"


 
McSimm ©   (2009-10-08 21:25) [11]

объяви свою константу ORIGINAL_ERROR_LEVEL в момент регистрации хендлера.


 
Piter ©   (2009-10-08 21:26) [12]

офигеть, это уже на какие-то мега-костыли похоже... Ради недопущеная принта стандартной функции они изменяют значение error_reporting()?! Получается так...


 
Piter ©   (2009-10-08 21:32) [13]

ну да, очевидное решение... Что-то я тупанул, столько времени потерял, пытаясь во всем этом разобраться блин..

Спасибо, Максим!


 
Piter ©   (2009-10-08 21:57) [14]

а если уж пошла такая пьянка насчет PHP... Вот есть вопрос - не могу определить логику.

Этот class Error в движке имеет метод display, который и выводит все накопленные ошибки на экран:

class Error ...
...
public function display($error_reporting = NULL)
   {
       $errortype = array
       (
           E_ERROR           => "Error",
           E_WARNING         => "Warning",
           E_PARSE           => "Parsing Error",
           E_NOTICE          => "Notice",
           E_CORE_ERROR      => "Core Error",
           E_CORE_WARNING    => "Core Warning",
           E_COMPILE_ERROR   => "Compile Error",
           E_COMPILE_WARNING => "Compile Warning",
           E_USER_ERROR      => "User Error",
           E_USER_WARNING    => "User Warning",
           E_USER_NOTICE     => "User Notice",
           E_STRICT          => "Runtime Notice"
       );

       if (!isset($error_reporting))
       {
           $error_reporting = $this->ORIGINAL_ERROR_LEVEL;
       }
       foreach ($this->stack as $error)
       {
           if ( ($error[0] & $error_reporting) != $error[0] )
           {
               continue;
           }

           $errno = isset($errortype[$error[0]])
                  ? $errortype[$error[0]]
                  : "Unknown error";

           echo "".$errno.": ".$error[1]." in file ".$error[2].
           "
on line ".$error[3].""."<br />\n";
       }
   }


Но интересно - когда по замыслу создателей он должен вызываться? Создается он в одном месте:

$Registry->Error = new Error(DEBUG);

Нигде больше по коду движка я не вижу строчек "$Registry->Error"

У самого класса есть деструктор:

public function __destruct()
   {
       $this->display();
   }


Соответственно, вопросы:

1) создать новый класс я понимаю так: "new ClassType", а как удалить существующий класс вручную?

2) если экземпляр класса не уничтожен, то PHP в конце обработки скрипта вызывает деструкторы всех этих объектов?

3) если вызывает - то в деструкторе класса может быть какой-то вывод, с помощью того же echo?

Если так не работает, то на что надеялись разработчики, когда они планировали выводишь накапливаемые ошибки:

public function general($errno, $errmsg, $filename, $linenum, $vars)
   {
       $this->addStack($errno, $errmsg, $filename, $linenum);
   }


Где интересно можно искать? Где вообще это можно сделать?


 
McSimm ©   (2009-10-08 22:15) [15]


> а как удалить существующий класс вручную?

$instance = null


> вызывает деструкторы всех этих объектов?

да


> в деструкторе класса может быть какой-то вывод, с помощью
> того же echo?

конечно.


 
Piter ©   (2009-10-08 22:31) [16]

тогда нифига не понятно... Вот это весь код класса:

class Error
{
   private $debug = FALSE;
   private $stack = array();
   private $ORIGINAL_ERROR_LEVEL = 0;

   public function __construct($debug = FALSE)
   {
       $this->debug = (bool) $debug;
       $this->ORIGINAL_ERROR_LEVEL = error_reporting();
       // xdebug_disable();
   }

   public function __destruct()
   {
       $this->display();
   }

   public function general($errno, $errmsg, $filename, $linenum, $vars)
   {
       $this->addStack($errno, $errmsg, $filename, $linenum);
   }

   public function pear($PEAR_Error)
   {
       echo $PEAR_Error->message.BR;

       if ($this->debug)
       {
           echo $PEAR_Error->userinfo.BR;
       }
       else
       {
           echo "<!-- ".$PEAR_Error->userinfo." -->".LF;
       }

       exit;
   }

   public function display($error_reporting = NULL)
   {
       $errortype = array
       (
           E_ERROR           => "Error",
           E_WARNING         => "Warning",
           E_PARSE           => "Parsing Error",
           E_NOTICE          => "Notice",
           E_CORE_ERROR      => "Core Error",
           E_CORE_WARNING    => "Core Warning",
           E_COMPILE_ERROR   => "Compile Error",
           E_COMPILE_WARNING => "Compile Warning",
           E_USER_ERROR      => "User Error",
           E_USER_WARNING    => "User Warning",
           E_USER_NOTICE     => "User Notice",
           E_STRICT          => "Runtime Notice"
       );

       if (!isset($error_reporting))
       {
           $error_reporting = $this->ORIGINAL_ERROR_LEVEL;
       }
       foreach ($this->stack as $error)
       {
           if ( ($error[0] & $error_reporting) != $error[0] )
           {
               continue;
           }

           $errno = isset($errortype[$error[0]])
                  ? $errortype[$error[0]]
                  : "Unknown error";

           echo "".$errno.": ".$error[1]." in file ".$error[2].
           "
on line ".$error[3].""."<br />\n";
       }
   }

   private function addStack($errno, $errmsg, $filename, $linenum)
   {
       $this->stack[] = array($errno, $errmsg, $filename, $linenum);
   }
}


На метод general соответственно перенаправлены выводы ошибок стандартных:

$Registry->Error = new Error(DEBUG);
set_error_handler(array($Registry->Error, "general"));


И все ок, ошибки добавляются в stack. Если я вызываю во время выполнения display - то они на экран выводятся. Но если вручную display не вызывать - по окочанию работы скрипта никаких ошибок нет.

Возможно, скрипт оканчивается по exit или die... Это влияет?
И куда тогда смотреть, почему в деструкторе не выводятся ошибки, хотя они есть...


 
McSimm ©   (2009-10-08 22:53) [17]


> Возможно, скрипт оканчивается по exit или die... Это влияет?

нет.

Трудно сказать
буфферизация вывода используется?
смотришь результат в консоли или браузере?


 
McSimm ©   (2009-10-08 23:07) [18]

проверил, минимальный пример у меня работает.


 
Piter ©   (2009-10-08 23:10) [19]

буферизация вроде не используется... А как проверить?
Могу сказать, что если метод заменить на:

public function general($errno, $errmsg, $filename, $linenum, $vars)
  {
      $this->addStack($errno, $errmsg, $filename, $linenum);
      $this->display();
  }


то ошибки на ура выводятся...

Есть команда, после которой echo ничего не сможет выводить на экран может? (((

Результат смотрю в браузере.

Если выводить сразу по мере поступления ошибки - все ок. Если дожидаться как в деструкторе вывод - фиг.Вообще ничего не выводится.


 
McSimm ©   (2009-10-08 23:16) [20]


> Результат смотрю в браузере.

может там после </html> все ?


 
Piter ©   (2009-10-08 23:49) [21]

может быть!!! я в мозиле нажимаю "Исходный код страницы"

Он может не отображать то что после HTML, даже если получил?


 
Piter ©   (2009-10-08 23:52) [22]

хотя не, не вариант. Скрипт ведь 100% прерывался на строчке connect, там где-то exit стоит... Значит, даже если где-то пишется </html> - оно не смогло бы написаться...


 
McSimm ©   (2009-10-09 00:25) [23]

ну, если, например, используется буферизирующий шаблонизатор какой-нибудь... там всякое может быть.

по Fatal Error при каких-то условиях может тихо умереть, без вывода.


 
McSimm ©   (2009-10-09 00:27) [24]

вот, кстати, если у класса $Registry в деструкторе произойдет Fatal, то вроде бы все именно так и будет происходить - никакого вывода о фатале, никакого вызова деструтора для Error


 
Piter ©   (2009-10-09 01:39) [25]

да класс registry вроде очень простой:

<?php
class Registry
{
   private $data = array();

   static public function instance()
   {
       static $instance;
       if (!isset($instance))
       {
           $instance = new Registry();
       }

       return $instance;
   }

   public function __get($name)
   {
       return @$this->data[$name];
   }

   public function __set($name, $value)
   {
       $this->data[$name] = $value;
   }
}
?>


 
Piter ©   (2009-10-09 01:41) [26]

кстати, я не понимаю когда пишут подавление... Вот почему здесь так:

@$this->data[$name];

а не например так:

$this->@data[$name];


 
McSimm ©   (2009-10-09 01:55) [27]

Тут в большей мере, наверное, привычка и читабельность, чем какие-либо программные критерии.
(Лучше вообще не использовать.)



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2009.12.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.006 c
8-1201846793
ZMRaven
2008-02-01 09:19
2009.12.06
Картинка с экрана


6-1180454227
AlexanderMS
2007-05-29 19:57
2009.12.06
Работа с локальной сетью.


2-1255623783
Nucer
2009-10-15 20:23
2009.12.06
Пустая ли строка


15-1254898716
Александр Ильин
2009-10-07 10:58
2009.12.06
Восстановление файла


2-1255952808
Fedor
2009-10-19 15:46
2009.12.06
Нажать кнопку ОК в javascript окне WebBrowser а





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский