- Using an Exception Handler
- Example 1
- Example 2
- Example 3
- SetUnhandledExceptionFilter function (errhandlingapi.h)
- Syntax
- Parameters
- Return value
- Remarks
- set_exception_handler — Задает пользовательский обработчик исключений
- Описание
- Список параметров
- Возвращаемые значения
- Список изменений
- Примеры
- Смотрите также
- Exception Handler. Handle Exception(Exception) Метод
- Определение
- Параметры
- Возвращаемое значение
- Примеры
- Комментарии
- set_exception_handler
- Описание
- Список параметров
- Возвращаемые значения
- Список изменений
- Примеры
- Смотрите также
- User Contributed Notes 19 notes
Using an Exception Handler
The following examples demonstrate the use of an exception handler.
Example 1
The following code fragment uses structured exception handling to check whether a division operation on two 32-bit integers will result in an division-by-zero error. If this occurs, the function returns FALSE— otherwise it returns TRUE.
Example 2
The following example function calls the DebugBreak function and uses structured exception handling to check for a breakpoint exception. If one occurs, the function returns FALSE— otherwise it returns TRUE.
The filter expression in the example uses the GetExceptionCode function to check the exception type before executing the handler. This enables the system to continue its search for an appropriate handler if some other type of exception occurs.
Also, use of the return statement in the __try block of an exception handler differs from the use of return in the __try block of a termination handler, which causes an abnormal termination of the __try block. This is an valid use of the return statement in an exception handler.
Only return EXCEPTION_EXECUTE_HANDLER from an exception filter when the exception type is expected and the faulting address is known. You should allow the default exception handler to process unexpected exception types and faulting addresses.
Example 3
The following example shows the interaction of nested handlers. The RaiseException function causes an exception in the guarded body of a termination handler that is inside the guarded body of an exception handler. The exception causes the system to evaluate the FilterFunction function, whose return value in turn causes the exception handler to be invoked. However, before the exception-handler block is executed, the __finally block of the termination handler is executed because the flow of control has left the __try block of the termination handler.
SetUnhandledExceptionFilter function (errhandlingapi.h)
Enables an application to supersede the top-level exception handler of each thread of a process.
After calling this function, if an exception occurs in a process that is not being debugged, and the exception makes it to the unhandled exception filter, that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.
Syntax
Parameters
A pointer to a top-level exception filter function that will be called whenever the UnhandledExceptionFilter function gets control, and the process is not being debugged. A value of NULL for this parameter specifies default handling within UnhandledExceptionFilter.
The filter function has syntax similar to that of UnhandledExceptionFilter: It takes a single parameter of type LPEXCEPTION_POINTERS, has a WINAPI calling convention, and returns a value of type LONG. The filter function should return one of the following values.
Value | Meaning |
---|---|
EXCEPTION_EXECUTE_HANDLER 0x1 | Return from UnhandledExceptionFilter and execute the associated exception handler. This usually results in process termination. |
EXCEPTION_CONTINUE_EXECUTION 0xffffffff | Return from UnhandledExceptionFilter and continue execution from the point of the exception. Note that the filter function is free to modify the continuation state by modifying the exception information supplied through its LPEXCEPTION_POINTERS parameter. |
EXCEPTION_CONTINUE_SEARCH 0x0 | Proceed with normal execution of UnhandledExceptionFilter. That means obeying the SetErrorMode flags, or invoking the Application Error pop-up message box. |
Return value
The SetUnhandledExceptionFilter function returns the address of the previous exception filter established with the function. A NULL return value means that there is no current top-level exception handler.
Remarks
Issuing SetUnhandledExceptionFilter replaces the existing top-level exception filter for all existing and all future threads in the calling process.
The exception handler specified by lpTopLevelExceptionFilter is executed in the context of the thread that caused the fault. This can affect the exception handler’s ability to recover from certain exceptions, such as an invalid stack.
set_exception_handler — Задает пользовательский обработчик исключений
set_exception_handler — Задает пользовательский обработчик исключений
Описание
Задает обработчик по умолчанию для случаев, когда исключение выброшено вне блока try/catch. После вызова exception_handler выполнение будет остановлено.
Список параметров
Имя функции, которая будет вызываться каждый раз, когда выбрасывается неперехватываемое исключение. Функция-обработчик должна принимать один аргумент — объект, представляющий выброшенное исключение.
В качестве этого аргумента можно передать NULL . В этом случае обработчик вернется к своему изначальному состоянию.
Возвращаемые значения
Возвращает имя предыдущего заданного обработчика или NULL в случае ошибки. Если предыдущих обработчиков определено не было, то также возвращается NULL .
Список изменений
Версия | Описание |
---|---|
5.5.0 | Раньше, если был передан NULL , то эта функция возвращала TRUE . Теперь она возвращает старый обработчик. |
Примеры
Пример #1 Пример использования set_exception_handler()
function exception_handler ( $exception ) <
echo «Неперехватываемое исключение: » , $exception -> getMessage (), «\n» ;
>
throw new Exception ( ‘Неперехватываемое исключение’ );
echo «Не выполнено\n» ;
?>
Смотрите также
- restore_exception_handler() — Восстанавливает предыдущий обработчик исключений
- restore_error_handler() — Восстанавливает предыдущий обработчик ошибок
- error_reporting() — Задает, какие ошибки PHP попадут в отчет
- информация о типе callback
- Исключения PHP 5
Exception Handler. Handle Exception(Exception) Метод
Определение
При переопределении в производном классе возвращает значение true , если исключение было обработано, или значение false , если исключение необходимо заново генерировать, а приложение закрыть. When overridden in a derived class, returns true if the exception has been handled, or false if the exception should be rethrown and the application terminated.
Параметры
Исключение, произошедшее во время работы Windows Communication Foundation (WCF) и которое может закрыть приложение. The exception the occurred within the Windows Communication Foundation (WCF) runtime and which may terminate the application.
Возвращаемое значение
true , если исключение обработано; в противном случае — false . true if the exception has been handled; otherwise, false .
Примеры
В следующем образце кода показана реализация абстрактного класса ExceptionHandler, который переопределяет метод HandleException. The following code example shows an implementation of the ExceptionHandler abstract class that overrides the HandleException method.
В следующем примере кода показано, как включить пользовательский MyExceptionHandler для необработанных исключений, происходящих в среде выполнения WCF. The following code example shows how to enable the custom MyExceptionHandler for unhandled exceptions that occur within the WCF runtime.
Комментарии
Свойство HandleException возвращает значение true , если исключение было обработано. The HandleException property returns true if the exception has been handled. Если оно возвращает значение false или выдает другое исключение, то исходное исключение генерируется заново. If it returns false or throws a different exception, the original exception is rethrown.
set_exception_handler
(PHP 5, PHP 7, PHP 8)
set_exception_handler — Задаёт пользовательский обработчик исключений
Описание
Задаёт обработчик по умолчанию для случаев, когда исключение выброшено вне блока try/catch. После вызова exception_handler выполнение будет остановлено.
Список параметров
Имя функции, которая будет вызываться каждый раз, когда выбрасывается неперехватываемое исключение. Функция-обработчик должна принимать один аргумент — объект, представляющий выброшенное исключение. До PHP 7 такая функция выглядит так:
В PHP 7 большинство внутренних ошибок теперь генерируют исключение, но класса Error. Для них также будет вызываться указанный обработчик исключений. Классы Error и Exception реализуют интерфейс Throwable, соответственно именно его следует использовать в сигнатуре функции-обработчика:
В качестве этого аргумента можно передать null . В этом случае обработчик вернётся к своему изначальному состоянию.
Указание типа Exception для параметра ex в вашей функции-обработчике приведёт к проблемам в PHP 7 из-за изменённой иерархии классов исключений.
Возвращаемые значения
Возвращает имя предыдущего заданного обработчика или null в случае ошибки. Если предыдущих обработчиков определено не было, то также возвращается null .
Список изменений
Версия | Описание |
---|---|
7.0.0 | Тип параметра передаваемого в exception_handler изменён с Exception на Throwable |
5.5.0 | Раньше, если был передан null , то эта функция возвращала true . Теперь она возвращает старый обработчик. |
Примеры
Пример #1 Пример использования set_exception_handler()
function exception_handler ( $exception ) <
echo «Неперехваченное исключение: » , $exception -> getMessage (), «\n» ;
>
throw new Exception ( ‘Неперехваченное исключение’ );
echo «Не выполнено\n» ;
?>
Смотрите также
- restore_exception_handler() — Восстанавливает предыдущий обработчик исключений
- restore_error_handler() — Восстанавливает предыдущий обработчик ошибок
- error_reporting() — Задаёт, какие ошибки PHP попадут в отчёт
- Исключения PHP 5
User Contributed Notes 19 notes
Things you should be aware of:
An exception handler handles exceptions that were not caught before. It is the nature of an exception that it discontinues execution of your program — since it declares an exceptional situation in which the program cannot continue (except you catch it).
Since it has not been catched your code signals it is not being aware of the situation and cant go on.
This implies: returning to the script is simply impossible when the exception handler has already been called, since an uncaught exception is not a notice. use your own debug- or notice-log-system for things like that.
Furthermore: While is is still possible to call functions from your script, since the exception handler has already been called exceptions bubbling from that piece of code won’t trigger the exception handler again. php will die without leaving any information apart form «uncaught exception with unknown stack frame». So if you call functions from your script, make sure that you catch any exceptions that possibly occur via try..catch inside the exception handler.
For those of you who misinterpreted the essential meaning of the exception handler: it’s only use is to handle the abortion of your script gracefully, e.g. in a project like facebook or wikipedia: render a nice error page, eventually hiding information which shall not leak into the public (instead you may want to write to your log or mail the sys-admin or stuff like that).
In other words: Redirecting all php-errors form an error-handler using exceptions — including notices — is a very dumb idea, if you do not intend having your script aborted everytime you didn’t set a variable (for example).
If you want a class instance to handle the exception, this is how you do it :
class example <
public function __construct () <
@ set_exception_handler (array( $this , ‘exception_handler’ ));
throw new Exception ( ‘DOH!!’ );
>
public function exception_handler ( $exception ) <
print «Exception Caught: » . $exception -> getMessage () . «\n» ;
>
>
$example = new example ;
?>
See the first post (Sean’s) for a static example. As Sean points out, the exception_handler function must be declared public.
A behaviour not documented or discussed enough, yet pretty common is that is that if an exception is thrown from the global exception handler then a fatal error occurs (Exception thrown without a stack frame). That is, if you define your own global exception handler by calling set_exception_handler() and you throw an exception from inside it then this fatal error occurs. It is only natural though, as the callback defined by set_exception_handler() is only called on uncaught (unhandled) exceptions so if you throw one from there then you get this fatal error as there is no exception handler left (you override the php internal one by calling set_exception_handler()), hence no stack frame for it.
function myExceptionHandler ( Exception $ex )
<
throw $ex ;
>
throw new Exception ( «This should cause a fatal error and this message will be lost» );
?>
Will cause a Fatal error: Exception thrown without a stack frame
If you skip/comment the set_exception_handler(«. «) line then the internal PHP global handler will catch the exception and output the exception message and trace (as string) to the browser, allowing you to at least see the exception message.
While it is a very good idea to always define your own global exception handler by using the set_exception_handler() function, you should pay attention and never throw an exception from it (or if you do then catch it).
Finally, every serious coder should use an IDE with debugging capabilities. Tracking down an error like this becomes a trivial matter by using simple debugging «Step into» commands (I for one recommend Zend IDE v5.2 at the moment of this writing). I have seen numerous messages on the internet with people wondering why this message pops up.
p.s. Other causes for this error which are somehow unrelated to this is when you throw an exception from a destructor (the reasons behind that are similar though, the global handler might no longer exist due to the php engine shutting the page down).
Hey all, i’ve just started to use the exception suite instead of the normal PHP error suite. For those of you looking for an object orientated way to do this without looking down at Glen and Sean’s examples (Lesson 1: ALWAYS read the logs!), here you go:
class NewException extends Exception
<
public function __construct ( $message , $code = NULL )
<
parent :: __construct ( $message , $code );
>
public function __toString ()
<
return «Code: » . $this -> getCode () . «
Message: » . htmlentities ( $this -> getMessage ());
>
public function getException ()
<
print $this ; // This will print the return from the above method __toString()
>
public static function getStaticException ( $exception )
<
$exception -> getException (); // $exception is an instance of this class
>
>
set_exception_handler (array( «NewException» , «getStaticException» ));
throw new NewException ( «Catch me. » , 69 );
?>
Let me know if i’m missing something obvious as I left my glasses at home and I just came back from the Melbourne cup (If I won then I wouldn’t be at work still!).
If you’re handling sensitive data and you don’t want exceptions logging details such as variable contents when you throw them, you may find yourself frustratedly looking for the bits and pieces that make up a normal stack trace output, so you can retain its legibility but just alter a few things. In that case, this may help you:
function exceptionHandler ( $exception ) <
// these are our templates
$traceline = «#%s %s(%s): %s(%s)» ;
$msg = «PHP Fatal error: Uncaught exception ‘%s’ with message ‘%s’ in %s:%s\nStack trace:\n%s\n thrown in %s on line %s» ;
// alter your trace as you please, here
$trace = $exception -> getTrace ();
foreach ( $trace as $key => $stackPoint ) <
// I’m converting arguments to their type
// (prevents passwords from ever getting logged as anything other than ‘string’)
$trace [ $key ][ ‘args’ ] = array_map ( ‘gettype’ , $trace [ $key ][ ‘args’ ]);
>
// build your tracelines
$result = array();
foreach ( $trace as $key => $stackPoint ) <
$result [] = sprintf (
$traceline ,
$key ,
$stackPoint [ ‘file’ ],
$stackPoint [ ‘line’ ],
$stackPoint [ ‘function’ ],
implode ( ‘, ‘ , $stackPoint [ ‘args’ ])
);
>
// trace always ends with
$result [] = ‘#’ . ++ $key . ‘
// write tracelines into main template
$msg = sprintf (
$msg ,
get_class ( $exception ),
$exception -> getMessage (),
$exception -> getFile (),
$exception -> getLine (),
implode ( «\n» , $result ),
$exception -> getFile (),
$exception -> getLine ()
);
// log or echo as you please
error_log ( $msg );
>
?>
If you’re not a fan of sprintf() or the duplicate $exception->getFile() and $exception->getLine() calls you can of course replace that as you like — consider this a mere compilation of the parts.
I’ve been messing around with this function, and have noticed you can pass an anonymous function (created with create_function()) through as the default handler, for example:
set_exception_handler(create_function(‘$e’, ‘exit(«An unknown error occurred»);’));
That snippet of code can be used if you simply want to suppress all exceptions that are not handled. This can be a great thing, because secure data could possibly be leaked otherwise (for example, the default exception handler could output a snippet of your SQL code that was involved with the exception being thrown).
You will want to use this wisely, however (if at all).
Your exception handler is configured to be the handler for all exceptions, yet if a basic ‘Exception’ is thrown, your static method will error because ‘Exception’s do not have ‘getException’. Because of this I don’t see a real purpose to making the uncaught handler a class that extends Exception.
I do like the idea of using static methods of a general Exception handling class.
class ExceptionHandler <
public static function printException ( Exception $e )
<
print ‘Uncaught ‘ . get_class ( $e ). ‘, code: ‘ . $e -> getCode () . «
Message: » . htmlentities ( $e -> getMessage ()). «\n» ;
>
public static function handleException ( Exception $e )
<
self :: printException ( $e );
>
>
set_exception_handler (array( «ExceptionHandler» , «handleException» ));
class NewException extends Exception <>
try <
throw new NewException ( «Catch me once» , 1 );
> catch ( Exception $e ) <
ExceptionHandler :: handleException ( $e );
>
throw new Exception ( «Catch me twice» , 2 );
?>
Gives:
Uncaught NewException, code: 1
Message: Catch me once
Uncaught Exception, code: 2
Message: Catch me twice
There are much more interesting things that can be done like reformating and optionally displaying or emailing them. But this class acts a nice container for those functions.
For those of you wanting to convert PHP errors to ErrorExceptions (useful), but frustrated with the script being halted on every E_NOTICE et al. In your error handler, simply create the ErrorException, and then either throw it (script halted), or pass the object directly (script continues) to your exception handler function.
const EXIT_ON_ALL_PHP_ERRORS = false ; // or true
function proc_error ( $errno , $errstr , $errfile , $errline )
<
$e = new ErrorException ( $errstr , 0 , $errno , $errfile , $errline );
if ( EXIT_ON_ALL_PHP_ERRORS ) <
throw $e ; // This will halt your script.
> else <
proc_exception ( $e ); // This will let it continue.
>
>
set_error_handler ( «proc_error» );
set_exception_handler ( «proc_exception» );
?>
You could further customize the error severity level (from $errno, match bitmasks with error level constants) at which the script is halted or allowed to continue. The above simply allows passthru for PHP errors’ default behavior.
If your exception handler is receiving both error ErrorExceptions (with severity level etc.) and other types of uncaught Exceptions, then use a if ( $e instanceof ErrorException ) < // . >?> condition to deal with the variance. I had to further wrap it into a try < $errno = $e ->getSeverity (); > catch ( Exception $x ) < $errno = 0 >. ?> , because some EE-s were mysteriously lacking the severity level property (yet to dig in and find out why).
On GNU/Linux, When an exception handler is called, PHP will end with exit status code 0 instead of 255.
You can change the exit status code with an exit() call at the end of your custom error handler.
Thanks to mastabog we know that throwing an exception within the exception handler will trigger a fatal error and a debugging nightmare. To avoid throwing an exception within there should be easy.
However, if you use a custom error handler to convert errors to ErrorExceptions suddenly there are a multitude of new ways to accidentally throw exceptions within the exception handler.
function error_handler ( $code , $message , $file , $line )
<
if ( 0 == error_reporting ())
<
return;
>
throw new ErrorException ( $message , 0 , $code , $file , $line );
>
function exception_handler ( $e )
<
// . normal exception stuff goes here
print $undefined ; // This is the underlying problem
>
set_error_handler ( «error_handler» );
set_exception_handler ( «exception_handler» );
throw new Exception ( «Just invoking the exception handler» );
?>
Output: Fatal error: Exception thrown without a stack frame in Unknown on line 0
The best way I have found to avoid this is to wrap up everything in the exception handler in a try/catch block.
function exception_handler ( $e )
<
try
<
// . normal exception stuff goes here
print $undefined ; // This is the underlying problem
>
catch ( Exception $e )
<
print get_class ( $e ). » thrown within the exception handler. Message: » . $e -> getMessage (). » on line » . $e -> getLine ();
>
>
?>
Output: ErrorException thrown within the exception handler. Message: Undefined variable: undefined on line 14
This speeds up debugging and offers some scalability to any other exceptions accidentally thrown within the exception handler.
Another solution is to restore the error handler at the beginning of the exception handler. While this is a silver bullet in terms of avoiding the ErrorExceptions, debugging messages then rely on the error_reporting() level and the display_errors directive. Why mention this? It might be preferable for production code since we care more about hiding errors from users than convenient debugging messages.
Using the ‘set_exception_handler’ function within a class, the defined ‘exception_handler’ method must be declared as ‘public’ (preferrable ‘public static’ if you use the «array(‘example’, ‘exception_handler’)» syntax).
class example <
public function __construct () <
@ set_exception_handler (array( ‘example’ , ‘exception_handler’ ));
throw new Exception ( ‘DOH!!’ );
>
public static function exception_handler ( $exception ) <
print «Exception Caught: » . $exception -> getMessage () . «\n» ;
>
>
$example = new example ;
echo «Not Executed\n» ;
?>
Declaring the ‘exception_handler’ function as ‘private’ causes a FATAL ERROR.
[derick: red. updated statement about static a bit]
As of PHP 7.4, an exception thrown within the user-defined shutdown function can be caught by the user-defined exception handler.
(
function( $level , $error , $file , $line ) <
if( 0 === error_reporting ()) <
return false ;
>
throw new ErrorException ( $error , — 1 , $level , $file , $line );
>,
E_ALL
);
register_shutdown_function (function() <
$error = error_get_last ();
if( $error ) <
throw new ErrorException ( $error [ ‘message’ ], — 1 , $error [ ‘type’ ], $error [ ‘file’ ], $error [ ‘line’ ]);
>
>);
set_exception_handler (function( $exception ) <
// . more code .
>);
Output: Fatal error: Exception thrown without a stack frame in Unknown on line 0
function error_handler ( $code , $message , $file , $line )
<
if ( 0 == error_reporting ())
<
return;
>
throw new ErrorException ( $message , 0 , $code , $file , $line );
>
function exception_handler ( $e )
<
// . normal exception stuff goes here
print $undefined ; // This is the underlying problem
>
set_error_handler ( «error_handler» );
set_exception_handler ( «exception_handler» );
throw new Exception ( «Just invoking the exception handler» );
?>
Now returns:
Fatal error: Uncaught exception ‘ErrorException’ with message ‘Undefined variable: undefined’ in C:\Apache2\htdocs\error\test.php:13 Stack trace: #0 C:\Apache2\htdocs\error\test.php(13): error_handler(8, ‘Undefined varia. ‘, ‘C:\Apache2\htdo. ‘, 13, Array) #1 [internal function]: exception_handler(Object(Exception)) #2
So it appears that exceptions thrown within exception handler now bypass exception handler.
This seems not to work when calling the PHP binary with the ‘-r’ flag.
For example, if I run it like this:
php -r ‘
function exception_handler($exception) <
echo «Uncaught exception: » , $exception->getMessage(), «\n»;
>
throw new Exception(«Uncaught Exception»);
echo «Not Executed\n»;
‘
Or if I place it in a file and run it like this:
php -r ‘include «./tmp.php»;’
I get a stack trace instead of having the function ‘exception_handler’ called. If run it like this:
(Why run code from ‘-r’? Sometimes it’s useful to add stuff around the include like calls to microtime for benchmarks, or to include a library and then call a few functions from the library, all in an ad-hoc way without having to create new files.)
PHP versions 5.1.2 and 5.0.4.
When an uncaught exception is handled, execution does NOT return to the script, but rather (unexpectedly, on my end anyway) terminates.
I am using set_error_handler() and set_exception_handler() in conjunction for a system I am currently developing (on v5.3.0 with Xampp). Lets say two E_USER_NOTICES are triggered, the script will die after the first one is processed.
( ‘exc_handler’ );
function exc_handler ( $exception ) <
echo «Uncaught exception: » , $exception -> getMessage (), «\n» ;
>
function errorone () <
throw new Exception ( «Test 1» );
>
function errortwo () <
throw new Exception ( «Test 2» );
>
function test () <
errorone ();
errortwo ();
>
test ();
test ();
?>
Instead of printing (as I’d expect) «Uncaught exception: Text 1\nUncaught exception: Text 2\nUncaught exception: Text 1\nUncaught exception: Text 2\n»
It is only printed ONCE. I’ve tried a number of different things, but I can’t figure out how to return execution to the script after the EXCEPTION HANDLER has run.
If anyone has a solution on how to return execution (hence, allow the script to log uncaught exceptions but continue processing) then PLEASE email me! Thanks!
Hi everyone. I don’t know if it is an old behavior of previous versions, but currently you can set exception and error handlers as private or protected methos, if, only if, you call `set_exception_handler()` or `set_error_handler()` within a context that can access the method.
Example:
= new class ()
<
public function __construct ()
<
set_error_handler ([ $this , ‘HandleError’ );
set_exception_handler ([ $this , ‘HandleException’ ]);
>
protected function HandleError ( $Code , $Message , $File = null , $Line = 0 , $Context = [] )
<
// Handle error here.
>
private function HandleException ( $Exception )
<
// Handle exception here.
>
>
?>
NOTE: these methods must match the callbacks parameters signatures. I put
In my experience, the static keyword is crucial for error handlers which are methods of a class instead of free-standing functions.
static function exceptionHandler($exception)
doesn’t and results in a «Fatal error: Exception thrown without a stack frame in Unknown on line 0» message.
«public» is optional as it is the default anyway (but it is probably clearer to write it explicitly).