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
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