Stephen Weeks wrote:
> Not long ago, Patrick R. Michaud proclaimed...
>> In August [1] I posted some code to test the ability to
>> resume execution after a thrown exception.  Here's a new
>> version of that code, updated for other recent changes
>> to Parrot's exceptions:
>>
>>   .sub main :main
>>       push_eh catcher
>>       'foo'()
>>       pop_eh
>>       say 'ok 4'
>>       .return ()
>>     catcher:
>>       .get_results ($P0)
>>       $P1 = $P0['resume']
>>       $P1()
>>   .end
>>
>>   .sub 'foo'
>>       say 'ok 1'
>>       $P0 = new 'Exception'
>>       throw $P0
>>       say 'ok 2'
>>       $P0 = new 'Exception'
>>       throw $P0
>>       say 'ok 3'
>>   .end
>>
>> As before, I'm simply trying to test the ability to
>> resume after exceptions thrown by C<foo>.
>>
>> Currently Parrot disables exception handlers when they're
>> invoked, thus the above results in "No exception handler"
>> when the second exception is thrown.  What do we need to
>> modify in Parrot so that the exception handler isn't
>> automatically disabled?
>>
>> (In response to my August message Allison noted that
>> we needed to update "legacy" exception handlers for the 
>> new model -- so I've begun the process of doing that update.
>> But now I need to know the appropriate patch or change to
>> make to Parrot so that it no longer disables handlers
>> upon invocation, so that I can complete the updates of
>> existing handlers.)
> 
> EHs are marked as "used" in src/scheduler.c:760

This line marks a handler as used, delete it:

  777    /* Mark that this handler has been used before. */
  778    VTABLE_set_integer_native(interp, handler, 1);

(Deleting that line does produce some nice infinite exceptions in 
t/pmc/threads.t.)

> src/pmc/exceptionhandler.pmc:214-219 contain the logic for "If I am
> marked as used, decline to handle the exception."  If you want to
> preserve the idea of a disabled exception handler still in the list of
> EHs in the context, you'll want to reorder the logic there so that it
> declines before it checks to see if a type or severity filter is in
> place.

This code you can leave for now, since it won't do anything if exception 
handlers are never disabled.


Stephen Weeks wrote:
 > Patrick R. Michaud wrote:
 >> I tried removing the above lines from exceptionhandler.pmc,
 >> but even after doing that my test program still gives the same
 >> results as before:
 >
 > I looked at it for a bit... the difference between the first and second
 > throw happens in Parrot_cx_find_handler_local
 >
 > The second time through, all of the checks for
 > !PMC_IS_NULL(context->handlers) fail.
 >
 > It looks like they are actually both getting the same context, but
 > between the first and second throw, ->handlers is set to PMCNULL.

The 'context->handlers' struct member should be PMCNULL in the 'foo' 
routine, because the handler was set in the outer 'main' routine. There 
are no handlers set in 'foo'. But, the search for handlers should find 
the handler in 'main' as it traverses the context chain outward.

Note that this example works just fine if all the code is in a single 
subroutine:

   .sub main :main
       push_eh catcher
       say 'ok 1'
       $P0 = new 'Exception'
       throw $P0
       say 'ok 2'
       $P0 = new 'Exception'
       throw $P0
       say 'ok 3'
       pop_eh
       say 'ok 4'
       .return ()
     catcher:
       .get_results ($P0)
       $P1 = $P0['resume']
       $P1()
   .end


So, the problem is caused by switching to the context of 'main' to 
execute the handler, and then switching back to the context of 'foo' 
when resuming. Maybe it's not really switching back to the 'foo' 
context, or maybe the chain of context->caller_ctx is disrupted by the 
resume.

Allison
_______________________________________________
http://lists.parrot.org/mailman/listinfo/parrot-dev

Reply via email to