Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.12.06;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.008 c
2-1254478034
Pavel
2009-10-02 14:07
2009.12.06
Перемещение полос прокрутки в ScrollBox/


2-1254662801
newbart
2009-10-04 17:26
2009.12.06
Ошибки при запуске приложений из Delphi


11-1208592364
<>
2008-04-19 12:06
2009.12.06
Много ли ресурсов потребляет невидимая форма?


3-1231075733
Oleg_teacher
2009-01-04 16:28
2009.12.06
Clientdatase + рисунок


15-1254741346
megamuz
2009-10-05 15:15
2009.12.06
Проследить за процессом