# New exceptions mechanism

- Thread: https://externals.io/message/7504
- Original archive: https://news-web.php.net/php.internals/7504
- Started by Andi Gutmans on 2004-02-03T13:01:12+00:00
- Messages: 7
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #7504 — Andi Gutmans — 2004-02-03T13:01:12+00:00

URL: https://externals.io/message/7504#7504

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 by `array_walk()`, it will only be caught when `array_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

---

## #7508 — mfischer@gjat.josefine@Markus Fischer — 2004-02-03T15:58:03+00:00

URL: https://externals.io/message/7504#7508 · In reply to: #7504

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

---

## #7593 — Marcus Boerger — 2004-02-04T22:29:59+00:00

URL: https://externals.io/message/7504#7593 · In reply to: #7504

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 by `array_walk()`, it will only be caught when `array_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

---

## #7597 — Zeev Suraski — 2004-02-04T23:40:43+00:00

URL: https://externals.io/message/7504#7597 · In reply to: #7504

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

---

## #7598 — Zeev Suraski — 2004-02-04T23:50:15+00:00

URL: https://externals.io/message/7504#7598 · In reply to: #7504

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:
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
>
>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

---

## #7691 — Andi Gutmans — 2004-02-10T10:24:55+00:00

URL: https://externals.io/message/7504#7691 · In reply to: #7504

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:
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
> > […]
>
>
>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

---

## #7774 — Marcus Boerger — 2004-02-11T22:39:28+00:00

URL: https://externals.io/message/7504#7774 · In reply to: #7691

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:
> > […]
