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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: randallgirard at hotmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2025 The PHP Group
All rights reserved.
Last updated: Sun Jun 29 21:01:32 2025 UTC