fsockopen вызывает ошибку FATAL, когда хост недоступен - "невозможно подключиться к"

Когда я вызываю fsockopen для недоступного IP-адреса, PHP останавливает выполнение с FATAL ERROR, как и предполагалось. Но для меня это нормальная ситуация, когда хост недоступен. Есть ли способ, как предотвратить остановку php даже в случае FATAL ERROR, если это предполагаемое поведение?

Я не использую никаких фреймворков, я сама обрабатываю все ошибки. Я регистрирую обработчики как это:

set_error_handler("errorHandler");
register_shutdown_function("fatalErrorHandler");

и обработчики определены так:

function fatalErrorHandler() 
{
    $error = error_get_last();

    if( $error !== NULL) {
      $errno   = $error["type"];
      $errfile = $error["file"];
      $errline = $error["line"];
      $errstr  = $error["message"];

      errorHandler($errno, "FATAL: " . $errstr, $errfile, $errline,get_defined_vars(),debug_backtrace());
    }
} 

function errorHandler($errno, $errstr, $errfile, $errline,$vars,$trace="")
{

   // some formatting and checking

   file_put_contents(dirname(__FILE__) . "/error/" . gmdate("YmdHis") . str_replace(".","",microtime(true)) . ".err"
  ,"<error_log_date>" . gmdate("YmdHis") . "</error_log_date><error_log_uid>{$uid}</error_log_uid>
   <error_log_str>{$errstr}</error_log_str>
   <error_log_file>{$errfile}</error_log_file>
   <error_log_line>{$errline}</error_log_line>
   <error_log_vars>{$vars}</error_log_vars>
   <error_log_trace>{$trace}</error_log_trace>");


 return true;
}

1 ответ

Решение

Окончательный ответ после того, как вопрос был отредактирован

Вы не знаете о том, что функция завершения вызывается в конце скрипта, независимо от того, произошли ошибки или нет. И даже если это было просто предупреждение, которое не остановило скрипт, сразу же error_get_last() вернет его. Дальше вы просто ставите FATAL:, закодированный перед сообщением. Вы должны обрабатывать различные типы ошибок, предупреждений и уведомлений здесь.

Проблема заключается в функции выключения, а не fsockopen(), Функция выключения должна выглядеть так:

register_shutdown_function(function() {
    $error = error_get_last();
    if($error && $error['type'] === E_ERROR) {

        $errno   = $error["type"];
        $errfile = $error["file"];
        $errline = $error["line"];
        $errstr  = $error["message"];

        errorHandler($errno, "FATAL: " . $errstr, $errfile, $errline /* , ... */);
    }   
});

Оригинальный ответ

Вы сказали, что PHP stops execution with FATAL ERROR,

Это неправда. fsockopen вернет false и выдаст предупреждение (!) в случае ошибки:

// sorry example.com ;)
var_dump(fsockopen("www.example.com", 1000, $errno, $errstr, 3));

Предупреждение PHP: fsockopen(): невозможно подключиться к www.example.com:1000 (истекло время ожидания подключения) в /home/thorsten/src/checkout-plugin/a.php в строке 3 Трассировка стека PHP: PHP 1. {main}() /home/thorsten/src/checkout-plugin/a.php:0 PHP 2. fsockopen() /home/thorsten/src/checkout-plugin/a.php:3 bool(false)

Если вы получаете фатальную ошибку, это может быть вызвано глобальным обработчиком ошибок, который был зарегистрирован с помощью set_error_handler() и превращает предупреждения в исключения. Некоторые рамки делают это. Если это правда, вы можете использовать оператор "тишины" @ подавить предупреждение:

var_dump(@fsockopen("www.example.com", 1000, $errno, $errstr, 3));
// bool(false)
Другие вопросы по тегам