cvs: ZendEngine2(PHP_5_3) / zend_exceptions.c zend_exceptions.h zend_objects.c /tests exception_007.phpt exception_008.phpt gc_030.phpt

"Marcus Boerger" <[email protected]>
Newsgroups gmane.comp.php.cvs.zend,gmane.comp.php.documentation.general
Message-ID <cvshelly1215985369@cvsserver>
helly		Sun Jul 13 21:42:49 2008 UTC

  Added files:                 (Branch: PHP_5_3)
    /ZendEngine2/tests	exception_007.phpt exception_008.phpt 

  Modified files:              
    /ZendEngine2	zend_exceptions.c zend_exceptions.h zend_objects.c 
    /ZendEngine2/tests	gc_030.phpt 
  Log:
  - MFH Exception handling
  [DOC]
  - Exceptions can be thrown while exceptions are pending, they are linked
  - Exceptions can be handled in __destruct
  - Add optional Exception $previous parameter to
    . Exception::__construct
    . ErrorException::__construct

-- 
Zend Engine CVS Mailing List (http://cvs.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
helly-20080713214249.txt (text/plain, 8.9 KB)
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_exceptions.c?r1=1.79.2.6.2.9.2.10&r2=1.79.2.6.2.9.2.11&diff_format=u
Index: ZendEngine2/zend_exceptions.c
diff -u ZendEngine2/zend_exceptions.c:1.79.2.6.2.9.2.10 ZendEngine2/zend_exceptions.c:1.79.2.6.2.9.2.11
--- ZendEngine2/zend_exceptions.c:1.79.2.6.2.9.2.10	Sun Jul 13 09:32:46 2008
+++ ZendEngine2/zend_exceptions.c	Sun Jul 13 21:42:49 2008
@@ -19,7 +19,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_exceptions.c,v 1.79.2.6.2.9.2.10 2008/07/13 09:32:46 tony2001 Exp $ */
+/* $Id: zend_exceptions.c,v 1.79.2.6.2.9.2.11 2008/07/13 21:42:49 helly Exp $ */
 
 #include "zend.h"
 #include "zend_API.h"
@@ -33,13 +33,37 @@
 static zend_object_handlers default_exception_handlers;
 ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
 
+void zend_exception_set_previous(zval *add_previous TSRMLS_DC)
+{
+	zval *exception = EG(exception), *previous;
+
+	if (exception == add_previous || !add_previous) {
+		return;
+	}
+	if (Z_TYPE_P(add_previous) != IS_OBJECT && !instanceof_function(Z_OBJCE_P(add_previous), default_exception_ce TSRMLS_CC)) {
+		zend_error(E_ERROR, "Cannot set non exception as previous exception");
+		return;
+	}
+	if (!exception) {
+		EG(exception) = add_previous;
+		return;
+	}
+	while (exception && exception != add_previous && Z_OBJ_HANDLE_P(exception) != Z_OBJ_HANDLE_P(add_previous)) {
+		previous = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 1 TSRMLS_CC);
+		if (Z_TYPE_P(previous) == IS_NULL) {
+			zend_update_property(default_exception_ce, exception, "previous", sizeof("previous")-1, add_previous TSRMLS_CC);
+			return;
+		}
+		exception = previous;
+	}
+}
+
 void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
 {
 	if (exception != NULL) {
-		if (EG(exception)) {
-			zend_update_property(default_exception_ce, exception, "previous", sizeof("previous")-1, EG(exception) TSRMLS_CC);
-		}
+		zval *previous = EG(exception);
 		EG(exception) = exception;
+		zend_exception_set_previous(previous TSRMLS_CC);
 	}
 	if (!EG(current_execute_data)) {
 		zend_error(E_ERROR, "Exception thrown without a stack frame");
@@ -129,8 +153,8 @@
 	zval  *object, *previous = NULL;
 	int    argc = ZEND_NUM_ARGS(), message_len;
 
-	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|slO", &message, &message_len, &code, &previous, default_exception_ce) == FAILURE) {
-		zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code ]])");
+	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|slO!", &message, &message_len, &code, &previous, default_exception_ce) == FAILURE) {
+		zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]])");
 	}
 
 	object = getThis();
@@ -158,8 +182,8 @@
 	zval  *object, *previous = NULL;
 	int    argc = ZEND_NUM_ARGS(), message_len, filename_len;
 
-	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllslO", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, default_exception_ce) == FAILURE) {
-		zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno ]]]]])");
+	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, default_exception_ce) == FAILURE) {
+		zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno  [, Exception $previous = NULL]]]]]])");
 	}
 
 	object = getThis();
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_exceptions.h?r1=1.21.2.1.2.2.2.1&r2=1.21.2.1.2.2.2.2&diff_format=u
Index: ZendEngine2/zend_exceptions.h
diff -u ZendEngine2/zend_exceptions.h:1.21.2.1.2.2.2.1 ZendEngine2/zend_exceptions.h:1.21.2.1.2.2.2.2
--- ZendEngine2/zend_exceptions.h:1.21.2.1.2.2.2.1	Mon Dec 31 07:17:04 2007
+++ ZendEngine2/zend_exceptions.h	Sun Jul 13 21:42:49 2008
@@ -19,13 +19,15 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_exceptions.h,v 1.21.2.1.2.2.2.1 2007/12/31 07:17:04 sebastian Exp $ */
+/* $Id: zend_exceptions.h,v 1.21.2.1.2.2.2.2 2008/07/13 21:42:49 helly Exp $ */
 
 #ifndef ZEND_EXCEPTIONS_H
 #define ZEND_EXCEPTIONS_H
 
 BEGIN_EXTERN_C()
 
+ZEND_API void zend_exception_set_previous(zval *add_previous TSRMLS_DC);
+
 void zend_throw_exception_internal(zval *exception TSRMLS_DC);
 
 void zend_register_default_exception(TSRMLS_D);
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_objects.c?r1=1.56.2.3.2.6.2.3&r2=1.56.2.3.2.6.2.4&diff_format=u
Index: ZendEngine2/zend_objects.c
diff -u ZendEngine2/zend_objects.c:1.56.2.3.2.6.2.3 ZendEngine2/zend_objects.c:1.56.2.3.2.6.2.4
--- ZendEngine2/zend_objects.c:1.56.2.3.2.6.2.3	Tue Mar 18 14:10:43 2008
+++ ZendEngine2/zend_objects.c	Sun Jul 13 21:42:49 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_objects.c,v 1.56.2.3.2.6.2.3 2008/03/18 14:10:43 felipe Exp $ */
+/* $Id: zend_objects.c,v 1.56.2.3.2.6.2.4 2008/07/13 21:42:49 helly Exp $ */
 
 #include "zend.h"
 #include "zend_globals.h"
@@ -99,20 +99,7 @@
 		old_exception = EG(exception);
 		EG(exception) = NULL;
 		zend_call_method_with_0_params(&obj, object->ce, &destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
-		if (old_exception) {
-			if (EG(exception)) {
-				zend_class_entry *default_exception_ce = zend_exception_get_default(TSRMLS_C);
-				zval *file = zend_read_property(default_exception_ce, old_exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
-				zval *line = zend_read_property(default_exception_ce, old_exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
-
-				zval_ptr_dtor(&obj);
-				zval_ptr_dtor(&EG(exception));
-				EG(exception) = old_exception;
-				zend_error(E_ERROR, "Ignoring exception from %s::__destruct() while an exception is already active (Uncaught %s in %s on line %ld)", 
-					object->ce->name, Z_OBJCE_P(old_exception)->name, Z_STRVAL_P(file), Z_LVAL_P(line));
-			}
-			EG(exception) = old_exception;
-		}
+		zend_exception_set_previous(old_exception TSRMLS_CC);
 		zval_ptr_dtor(&obj);
 	}
 }
http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/gc_030.phpt?r1=1.1.2.1&r2=1.1.2.2&diff_format=u
Index: ZendEngine2/tests/gc_030.phpt
diff -u ZendEngine2/tests/gc_030.phpt:1.1.2.1 ZendEngine2/tests/gc_030.phpt:1.1.2.2
--- ZendEngine2/tests/gc_030.phpt:1.1.2.1	Tue Jul  8 08:16:09 2008
+++ ZendEngine2/tests/gc_030.phpt	Sun Jul 13 21:42:49 2008
@@ -18,4 +18,14 @@
 gc_collect_cycles();
 ?>
 --EXPECTF--
-Fatal error: Ignoring exception from foo::__destruct() while an exception is already active (Uncaught Exception in %sgc_030.php on line %d) in %sgc_030.php on line %d
+Fatal error: Uncaught exception 'Exception' with message 'foobar' in %sgc_030.php:%d
+Stack trace:
+#0 [internal function]: foo->__destruct()
+#1 %sgc_030.php(%d): gc_collect_cycles()
+#2 {main}
+
+Next exception 'Exception' with message 'foobar' in %sgc_030.php:%d
+Stack trace:
+#0 %sgc_030.php(%d): foo->__destruct()
+#1 {main}
+  thrown in %sgc_030.php on line %d
\ No newline at end of file

http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/exception_007.phpt?view=markup&rev=1.1
Index: ZendEngine2/tests/exception_007.phpt
+++ ZendEngine2/tests/exception_007.phpt
--TEST--
Setting previous exception
--FILE--
<?php

try {
	try {
		throw new Exception("First", 1, new Exception("Another", 0, NULL));
	}
	catch (Exception $e) {
		throw new Exception("Second", 2, $e);
	}
}
catch (Exception $e) {
	throw new Exception("Third", 3, $e);
}

?>
===DONE===
--EXPECTF--
Fatal error: Uncaught exception 'Exception' with message 'Another' in %sexception_007.php:%d
Stack trace:
#0 {main}

Next exception 'Exception' with message 'First' in %sexception_007.php:%d
Stack trace:
#0 {main}

Next exception 'Exception' with message 'Second' in %sexception_007.php:%d
Stack trace:
#0 {main}

Next exception 'Exception' with message 'Third' in %sexception_007.php:%d
Stack trace:
#0 {main}
  thrown in %sexception_007.php on line %d

http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/exception_008.phpt?view=markup&rev=1.1
Index: ZendEngine2/tests/exception_008.phpt
+++ ZendEngine2/tests/exception_008.phpt
--TEST--
Exception in __destruct while exception is pending
--FILE--
<?php

class TestFirst
{
	function __destruct() {
		throw new Exception("First");
	}
}

class TestSecond
{
	function __destruct() {
		throw new Exception("Second");		
	}
}

$ar = array(new TestFirst, new TestSecond);

unset($ar);

?>
===DONE===
--EXPECTF--
Fatal error: Uncaught exception 'Exception' with message 'First' in %sexception_008.php:%d
Stack trace:
#0 %sexception_008.php(%d): TestFirst->__destruct()
#1 {main}

Next exception 'Exception' with message 'Second' in %sexception_008.php:%d
Stack trace:
#0 %sexception_008.php(%d): TestSecond->__destruct()
#1 {main}
  thrown in %sexception_008.php on line %d
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.