Hi,
We rewrote the exception support. It fixes a few limitations and bugs in
the old implementation, and allows exceptions to 'fire' much earlier than
before.
Generally, with the new mechanism, you're not supposed to touch
EG(exception) directly, except for when you want to check whether there was
an exception (you're not allowed to directly modify EG(exception)).
-
Generally, to throw an exception you need to use
zend_throw_exception(). If you have special needs, and for some reason you
wish to bypass zend_throw_exception(), you can use
zend_throw_exception_internal(). Again, generally you shouldn't have to do
that, though. -
The new mechanism allows PHP to handle exceptions as soon as we return to
the context of the execute loop. Exceptions still cannot be caught inside
your extension code, as they can only be handled reliably in the context of
execute(). For example, if an exception is thrown in a callback function
that's called byarray_walk()
, it will only be caught whenarray_walk()
returns. -
Functions like
array_walk()
(typically functions that use
zend_call_function() or call_user_function_ex()) should decide whether they
want to abort when there is an exception, or ignore it. If you choose to
abort, and let the exception propagate up, then you should simply return
back as soon as you can. As soon as it reaches the execute loop - the
exception will be handled (i.e., if there's a corresponding catch block it
will be executed, or otherwise, the stack will unwind).
If you choose to ignore it - you should call
zend_clear_exception(TSRMLS_C). Note that you should make your choice and
behave accordingly BEFORE making any further calls to PHP functions (or any
code that may throw an exception). -
To check whether there was an exception, you should still use the same
method as before (check whether EG(exception) is not NULL), but again, you
may not change it directly under any circumstances.
Note - this (most probably) breaks the current implementation of
set_exception_handler()
so whoever is responsible for that piece of code
please look into it, and ask us if you have any questions.
Andi
I've a little issue with exception, however this isn't particular
bound to the new mechanism and existed before.
When calling a static method of a class from an objects method, the
stack trace does not reveal the class name of the static class
containing the static method.
Example:
$ cat test_exception.php
<?php
class StaticClass {
function staticMethod() {
throw new Exception("example");
}
}
class InstantiateMe {
function method() {
#throw new Exception("example");
StaticClass::staticMethod();
}
}
$obj = new InstantiateMe;
$obj->method();
?>
Output:
$ php test_exception.php
Fatal error: Uncaught exception 'exception' with message 'example' in /home/mfischer/htdocs/php5/test_exception.php:4
Stack trace:
#0 /home/mfischer/htdocs/php5/test_exception.php(11): InstantiateMe->staticMethod()
#1 /home/mfischer/htdocs/php5/test_exception.php(16): InstantiateMe->method()
#2 {main}
thrown in /home/mfischer/htdocs/php5/test_exception.php on line 4
Of special interest, see #0 containing the line:
InstantiateMe->staticMethod()
instead of e.g.
StaticClass::staticMethod()
At least, saying 'InstantiateMe->' looks wrong to me as I'm calling
'StaticClass::' actually.
- Markus
Hello Andi,
Tuesday, February 3, 2004, 2:01:12 PM, you wrote:
Hi,
We rewrote the exception support. It fixes a few limitations and bugs in
the old implementation, and allows exceptions to 'fire' much earlier than
before.
Generally, with the new mechanism, you're not supposed to touch
EG(exception) directly, except for when you want to check whether there was
an exception (you're not allowed to directly modify EG(exception)).
- Generally, to throw an exception you need to use
zend_throw_exception(). If you have special needs, and for some reason you
wish to bypass zend_throw_exception(), you can use
zend_throw_exception_internal(). Again, generally you shouldn't have to do
that, though.
- The new mechanism allows PHP to handle exceptions as soon as we return to
the context of the execute loop. Exceptions still cannot be caught inside
your extension code, as they can only be handled reliably in the context of
execute(). For example, if an exception is thrown in a callback function
that's called byarray_walk()
, it will only be caught whenarray_walk()
returns.
- Functions like
array_walk()
(typically functions that use
zend_call_function() or call_user_function_ex()) should decide whether they
want to abort when there is an exception, or ignore it. If you choose to
abort, and let the exception propagate up, then you should simply return
back as soon as you can. As soon as it reaches the execute loop - the
exception will be handled (i.e., if there's a corresponding catch block it
will be executed, or otherwise, the stack will unwind).
If you choose to ignore it - you should call
zend_clear_exception(TSRMLS_C). Note that you should make your choice and
behave accordingly BEFORE making any further calls to PHP functions (or any
code that may throw an exception).
- To check whether there was an exception, you should still use the same
method as before (check whether EG(exception) is not NULL), but again, you
may not change it directly under any circumstances.
Note - this (most probably) breaks the current implementation of
set_exception_handler()
so whoever is responsible for that piece of code
please look into it, and ask us if you have any questions.
Andi
The new exception implementation looks a bit nicer but needs some
tweaks. Try this code:
php -r 'reflection_class::export("xyz");'
which dirctly segfaults. What happens is that the class xyz does not exist
and reflection api throws an exception which results in a SEGV.
--
Best regards,
Marcus mailto:helly@php.net
At 00:29 05/02/2004, Marcus Boerger wrote:
The new exception implementation looks a bit nicer but needs some
tweaks. Try this code:
A bit? It's a helluva lot nicer :)
php -r 'reflection_class::export("xyz");'
which dirctly segfaults. What happens is that the class xyz does not exist
and reflection api throws an exception which results in a SEGV.
Yes, I think it's the same thing others are bumping into, but that's a very
nice short reproducing script you got there :) We'll fix it tomorrow.
Zeev
I submitted a fix for this (as I suspected, it appears to be more of a bug
in zend_call_function() than a bug in the new exceptions mechanism)... I'm
not 100% sure about this fix as I didn't have time to investigate it too
much, but it appears to be correct, and I wanted to allow you to go on
testing :) I'll check into it further tomorrow.
Zeev
At 00:29 05/02/2004, Marcus Boerger wrote:
Hello Andi,
Tuesday, February 3, 2004, 2:01:12 PM, you wrote:
Hi,
We rewrote the exception support. It fixes a few limitations and bugs in
the old implementation, and allows exceptions to 'fire' much earlier than
before.Generally, with the new mechanism, you're not supposed to touch
EG(exception) directly, except for when you want to check whether there was
an exception (you're not allowed to directly modify EG(exception)).
- Generally, to throw an exception you need to use
zend_throw_exception(). If you have special needs, and for some reason you
wish to bypass zend_throw_exception(), you can use
zend_throw_exception_internal(). Again, generally you shouldn't have to do
that, though.
- The new mechanism allows PHP to handle exceptions as soon as we return to
the context of the execute loop. Exceptions still cannot be caught inside
your extension code, as they can only be handled reliably in the context of
execute(). For example, if an exception is thrown in a callback function
that's called byarray_walk()
, it will only be caught whenarray_walk()
returns.
- Functions like
array_walk()
(typically functions that use
zend_call_function() or call_user_function_ex()) should decide whether they
want to abort when there is an exception, or ignore it. If you choose to
abort, and let the exception propagate up, then you should simply return
back as soon as you can. As soon as it reaches the execute loop - the
exception will be handled (i.e., if there's a corresponding catch block it
will be executed, or otherwise, the stack will unwind).
If you choose to ignore it - you should call
zend_clear_exception(TSRMLS_C). Note that you should make your choice and
behave accordingly BEFORE making any further calls to PHP functions (or any
code that may throw an exception).
- To check whether there was an exception, you should still use the same
method as before (check whether EG(exception) is not NULL), but again, you
may not change it directly under any circumstances.Note - this (most probably) breaks the current implementation of
set_exception_handler()
so whoever is responsible for that piece of code
please look into it, and ask us if you have any questions.Andi
The new exception implementation looks a bit nicer but needs some
tweaks. Try this code:
php -r 'reflection_class::export("xyz");'
which dirctly segfaults. What happens is that the class xyz does not exist
and reflection api throws an exception which results in a SEGV.--
Best regards,
Marcus mailto:helly@php.net
Does this still segfault for you? It doesn't for me.
Andi
At 11:29 PM 2/4/2004 +0100, Marcus Boerger wrote:
Hello Andi,
Tuesday, February 3, 2004, 2:01:12 PM, you wrote:
Hi,
We rewrote the exception support. It fixes a few limitations and bugs in
the old implementation, and allows exceptions to 'fire' much earlier than
before.Generally, with the new mechanism, you're not supposed to touch
EG(exception) directly, except for when you want to check whether there was
an exception (you're not allowed to directly modify EG(exception)).
- Generally, to throw an exception you need to use
zend_throw_exception(). If you have special needs, and for some reason you
wish to bypass zend_throw_exception(), you can use
zend_throw_exception_internal(). Again, generally you shouldn't have to do
that, though.
- The new mechanism allows PHP to handle exceptions as soon as we return to
the context of the execute loop. Exceptions still cannot be caught inside
your extension code, as they can only be handled reliably in the context of
execute(). For example, if an exception is thrown in a callback function
that's called byarray_walk()
, it will only be caught whenarray_walk()
returns.
- Functions like
array_walk()
(typically functions that use
zend_call_function() or call_user_function_ex()) should decide whether they
want to abort when there is an exception, or ignore it. If you choose to
abort, and let the exception propagate up, then you should simply return
back as soon as you can. As soon as it reaches the execute loop - the
exception will be handled (i.e., if there's a corresponding catch block it
will be executed, or otherwise, the stack will unwind).
If you choose to ignore it - you should call
zend_clear_exception(TSRMLS_C). Note that you should make your choice and
behave accordingly BEFORE making any further calls to PHP functions (or any
code that may throw an exception).
- To check whether there was an exception, you should still use the same
method as before (check whether EG(exception) is not NULL), but again, you
may not change it directly under any circumstances.Note - this (most probably) breaks the current implementation of
set_exception_handler()
so whoever is responsible for that piece of code
please look into it, and ask us if you have any questions.Andi
The new exception implementation looks a bit nicer but needs some
tweaks. Try this code:
php -r 'reflection_class::export("xyz");'
which dirctly segfaults. What happens is that the class xyz does not exist
and reflection api throws an exception which results in a SEGV.--
Best regards,
Marcus mailto:helly@php.net
Hello Andi,
it works now fine :-)
marcus
Tuesday, February 10, 2004, 11:24:55 AM, you wrote:
Does this still segfault for you? It doesn't for me.
Andi
At 11:29 PM 2/4/2004 +0100, Marcus Boerger wrote:
Hello Andi,
Tuesday, February 3, 2004, 2:01:12 PM, you wrote:
Hi,
We rewrote the exception support. It fixes a few limitations and bugs in
the old implementation, and allows exceptions to 'fire' much earlier than
before.Generally, with the new mechanism, you're not supposed to touch
EG(exception) directly, except for when you want to check whether there was
an exception (you're not allowed to directly modify EG(exception)).
- Generally, to throw an exception you need to use
zend_throw_exception(). If you have special needs, and for some reason you
wish to bypass zend_throw_exception(), you can use
zend_throw_exception_internal(). Again, generally you shouldn't have to do
that, though.
- The new mechanism allows PHP to handle exceptions as soon as we return to
the context of the execute loop. Exceptions still cannot be caught inside
your extension code, as they can only be handled reliably in the context of
execute(). For example, if an exception is thrown in a callback function
that's called byarray_walk()
, it will only be caught whenarray_walk()
returns.
- Functions like
array_walk()
(typically functions that use
zend_call_function() or call_user_function_ex()) should decide whether they
want to abort when there is an exception, or ignore it. If you choose to
abort, and let the exception propagate up, then you should simply return
back as soon as you can. As soon as it reaches the execute loop - the
exception will be handled (i.e., if there's a corresponding catch block it
will be executed, or otherwise, the stack will unwind).
If you choose to ignore it - you should call
zend_clear_exception(TSRMLS_C). Note that you should make your choice and
behave accordingly BEFORE making any further calls to PHP functions (or any
code that may throw an exception).
- To check whether there was an exception, you should still use the same
method as before (check whether EG(exception) is not NULL), but again, you
may not change it directly under any circumstances.Note - this (most probably) breaks the current implementation of
set_exception_handler()
so whoever is responsible for that piece of code
please look into it, and ask us if you have any questions.Andi
The new exception implementation looks a bit nicer but needs some
tweaks. Try this code:
php -r 'reflection_class::export("xyz");'
which dirctly segfaults. What happens is that the class xyz does not exist
and reflection api throws an exception which results in a SEGV.--
Best regards,
Marcus mailto:helly@php.net