On Mon, May 23, 2016 at 11:36 PM, Dmitry Stogov <dmi...@zend.com> wrote:

> Hi,
>
> On 05/23/2016 07:24 PM, Nikita Popov wrote:
>
> On Mon, May 23, 2016 at 1:25 PM, Dmitry Stogov <dmi...@zend.com> wrote:
>
>> Thanks for review.
>>
>> Both problems should be fixed now
>> <https://gist.github.com/dstogov/0a809891c6a3ac3fac4bd0d9711dd330>
>> https://gist.github.com/dstogov/0a809891c6a3ac3fac4bd0d9711dd330
>>
>> Do you see any other problems or a better way to fix this?
>>
> Your fix for DISCARD_EXCEPTION does not look right to me. It will discard
> all exceptions too early. For example:
>
> function test() {
>     try {
>         throw new Exception(1);
>     } finally {
>         try {
>             try {
>             } finally {
>                 return 42;
>             }
>         } finally {
>             throw new Exception(2);
>         }
>     }
> }
>
> test();
>
> This will now not chain exception 1 and 2, because exception 1 is
> discarded at the return statement.
>
>
> I thought about this, and I think that the current behavior is right.
> If we remove "throw new Exception(2);" the first exception is going to be
> discarded at "return 42;".
> I think we should do the same independently from the context.
>
> Why do you think Exception(1) should be kept?
>

Because Exception(3) may be discarded by another catch in the finally, in
which case we should throw Exception(1). Consider this case:

function test() {
    try {
        throw new Exception(1);
    } finally {
        try {
            try {
                try {
                } finally {
                    return 42;
                }
            } finally {
                throw new Exception(3);
            }
        } catch (Exception $e) {}
    }
}

test();

This should throw Exception(1), as Exception(3) is thrown and caught inside
the finally block. I thought your current patch would not throw anything in
this case, but I'm actually getting an assertion failure (and a conditional
jump on uninit value in valgrind):

php: /home/nikic/php-src/Zend/zend_gc.c:226: gc_possible_root: Assertion
`(ref)->gc.u.v.type == 7 || (ref)->gc.u.v.type == 8' failed.


> I think this should be handled the same way we do the fast_call dispatch
> on return, i.e. when we pop the FAST_CALL from the loop var stack we should
> replace it with a DISCARD_EXCEPTION and then pop it after the finally. This
> should generate all the necessary DISCARD_EXCEPTION opcodes, and in the
> right order.
>
>
> May be I'll commit the existing fix, and you'll try to implement this idea
> on top?
>
> Thanks. Dmitry.
>
>
> Nikita
>
>
>

Reply via email to