php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #50446 Missing documentation or bug for SET_EXCEPTION_HANDLER()
Submitted: 2009-12-11 02:44 UTC Modified: 2010-01-07 11:14 UTC
From: randallgirard at hotmail dot com Assigned:
Status: Not a bug Package: Documentation problem
PHP Version: 5.3.1 OS: Windows
Private report: No CVE-ID: None
 [2009-12-11 02:44 UTC] randallgirard at hotmail dot com
Description:
------------
The documentation does not state for the function set_exception_handler(...) that it will terminate processing. I do not see much of a reason for such a handler if you do not have this option. Unless I am missing something, please include such documentation or fix this in the next release. Take for example set_error_handler() which forces you to handle termination of the script (when necessary) from code.


NOTE: I am using v5.3.0 on my local machine for testing, and havent tested on my server which runs 5.3.1 but I doubt this is the case.

Reproduce code:
---------------
function exception_handler($exception) {
  echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

set_exception_handler('exception_handler');

	function errorone() {
		throw new Exception("Test 1");
	}
	function errortwo() {
		throw new Exception("Test 2");
	}
	function test() {
		errorone();
		errortwo();
	}
	test();
	test();

# I also did further tests involving class scopes that I thought might affect this, but I'm almost positive processing of the script is terminated without a way to restore it.

Expected result:
----------------
Uncaught exception: Test 1\nUncaught exception: Test 2\nUncaught exception: Test 1\nUncaught exception: Test 2\n

Actual result:
--------------
Uncaught exception: Test 1\n

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-12-11 09:34 UTC] rquadling@php.net
The example does show this, but some additional words may be useful.

 [2009-12-11 09:55 UTC] rquadling@php.net
As does the Description ...

"Execution will stop after the exception_handler is called."

Nothing additional required.
 [2009-12-11 19:41 UTC] randallgirard at hotmail dot com
What is the reason for this functionality, if you cannot return to processing of the script?
 [2009-12-11 20:08 UTC] bjori@php.net
To process *unhandled* exceptions.

If your application throws an exception you don't expect, then you *must* have an exception handler that catches that exception, logs it, and prints a pretty error page for your user.

Maybe we should add a tip or a better usecase/description? (re-opening)
 [2009-12-11 20:10 UTC] bjori@php.net
replace that "*must*" with an RCC2119 SHOULD
 [2009-12-11 20:11 UTC] randallgirard at hotmail dot com
I added a new bug for feature request at the following, explaining more of a WHY reason for such a situation.


Mainly in my situation though, is because I am combining SET_ERROR_HANDLER with SET_EXCEPTION_HANDLER, and the ERROR_HANDLER fires ErrorException, as noted in the documentation.


Therefor, even though my ERROR_HANDLER processes the $errnum correctly, script execution still terminates when for example E_USER_NOTICE or E_USER_WARNING happens, and no way for me to write a work around for this.
 [2009-12-11 20:13 UTC] randallgirard at hotmail dot com
Oops I forgot to supply the link, here ya go:

http://bugs.php.net/bug.php?id=50454
 [2009-12-11 20:21 UTC] randallgirard at hotmail dot com
HERE is my current error handler code that I wrote yesterday?

<?php
namespace frm {
	
# ------------- ERROR HANDLING
	
	abstract class error {
		
		public static $LIST = array();
		
		public static function initiate( $log = false ) {
		# setup error handling
		# NOTE: If namespaces are used, they must be specified in the below calls:
		#		ex: '\\my_namespace\\error::handler'
			set_error_handler( '\\frm\\error::err_handler' );
			set_exception_handler( '\\frm\\error::exc_handler' );
		# If $log is set (should be a file) then enable logging and set ERROR_LOG
			if ( $log !== false ) {
				if ( ! ini_get('log_errors') )
					ini_set('log_errors', true);
				if ( ! ini_get('error_log') )
					ini_set('error_log', $log);
			}
		}
		
	# Error handler (catch unhandled errors)
		public static function err_handler($errno, $errstr, $errfile, $errline, $errcontext) {
			$l = error_reporting();
			if ( $l & $errno ) {
				
			# determine error type and if we exit or not
				$exit = false;
			# The following error types are not supported because they get thrown BEFORE RUNTIME:
			# E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
				switch ( $errno ) {
					case E_USER_ERROR:
						$type = 'Fatal Error';
						$exit = true;
					break;
					case E_USER_WARNING:
					case E_WARNING:
						$type = 'Warning';
					break;
					case E_USER_NOTICE:
					case E_NOTICE:
				# error handling is for PHP versions < 5.2
					case @E_STRICT:
						$type = 'Notice';
					break;
					case @E_RECOVERABLE_ERROR:
						$type = 'Catchable';
					break;
				# unknown error type:
				# ...just in case a new error type is added
					default:
						$type = 'Unknown Error';
						$exit = true;
					break;
				}
				
				$exception = new \ErrorException($type.': '.$errstr, 0, $errno, $errfile, $errline);
				
				if ( $exit ) {
				# MAKE SURE we exit termination
					exc_handler($exception);
					exit();
				}
				else
				# NOTE: Uncaught exceptions cause the script to terminate processing and does NOT continue
					throw $exception;
			}
			return false;
		}
		
	# Exception handler - catch unhandled exceptions, perform logs, etc
		function exc_handler($exception) {
			$log = $exception->getMessage() . "\n" . $exception->getTraceAsString() . LINEBREAK;
		# log error if enabled
			if ( ini_get('log_errors') )
				error_log($log, 0);
			print("Unhandled Exception" . (DEBUG ? " - $log" : ''));
		}
		
	}
	
}
?>



Now, if an (for example) E_USER_WARNING or E_USER_NOTICE error is triggered without a TRY block in the parent scope then script execution terminates and doesn't allow me to control whether or not processing is terminated.
 [2009-12-11 20:32 UTC] bjori@php.net
Reading that code without syntax highlighting and weird lineendings is very hard.
However:

> Now, if an (for example) E_USER_WARNING or E_USER_NOTICE error
> is triggered without a TRY block in the parent scope then
> script execution terminates and doesn't allow me to control
> whether or not processing is terminated.

That is exactly the point.
If you do not catch exceptions then the application *MUST* die.

Exception aren't regular warnings/notices. Exceptions means something very very wrong happened. If you don't catch that exception and deal with it, then the application is in a state that it simply cannot continue.

Having a global exception *handler* is just a way for you to deal with the error (log it, send email/sms...). It does not replace a try/catch block.
 [2009-12-11 20:56 UTC] randallgirard at hotmail dot com
In other words, E_USER_NOTICE and E_USER_WARNING are both USELESS and act as E_USER_ERROR (considering the code terminates),,,, that is, when used as documented with ErrorException and an Error Handler.



I guess my only solution, then, is to NOT throw an exception for E_USER_NOTICE or E_USER_WARNING (or other non-exiting errors) and instead call the exception handler manually.


Of course Try/Catch blocks won't be able to catch such circumstances.
 [2009-12-11 22:47 UTC] bjori@php.net
Lets move the discussion to the discussion list: php-general@lists.php.net

(See: http://news.php.net/php.general/300410)
 [2010-01-07 11:14 UTC] kalle@php.net
The description for set_exception_handler() already says that it will stop execution after it catches an exception.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 21:01:36 2024 UTC