Ticket #944 (closed bug: fixed)

Opened 12 years ago

Last modified 11 years ago

Exception handling in top-level main function is broken.

Reported by: bacek Owned by:
Priority: normal Milestone:
Component: core Version: trunk
Severity: medium Keywords:
Cc: Language:
Patch status: Platform:

Description

Hello.

bacek@icering:~/src/parrot$ cat e2.pir 
.sub main :main
    $P0 = newclass 'Foo'
    $P0 = new ['Foo']
    push_eh catch
    $S0 = $P0
    say "huh?"
    .return()
catch:
    say "caught"
    .return()
.end

.namespace ['Foo']

.sub get_string :vtable :method
    $P0 = new ['Exception']
    throw $P0
.end

bacek@icering:~/src/parrot$ ./parrot e2.pir 
caught
huh?
Segmentation fault

-- Bacek

Change History

Changed 12 years ago by bacek

It's not "top-level main function". This code fails too.

.sub main :main
    foo()
.end

.sub foo
    $P0 = newclass 'Foo'
    $P0 = new ['Foo']
    push_eh catch
    $S0 = $P0
    say "huh?"
    .return()
catch:
    say "caught"
    .return()
.end

.namespace ['Foo']

.sub get_string :vtable :method
    $P0 = new ['Exception']
    throw $P0
.end

Changed 12 years ago by bacek

Ok, this is problem with VTABLEs. Replacing $S0 = $P0 with $S0 = $P0.'get_string'() produces correct results.

Changed 12 years ago by coke

On Mon, Aug 24, 2009 at 5:38 AM, Parrot<parrot-tickets@lists.parrot.org> wrote:
> #944: Exception handling in top-level main function is broken.
> --------------------+-------------------------------------------------------
>  Reporter:  bacek   |       Owner:
>     Type:  bug     |      Status:  new
>  Priority:  normal  |   Milestone:
> Component:  core    |     Version:  trunk
>  Severity:  medium  |    Keywords:
>     Lang:          |       Patch:
>  Platform:          |
> --------------------+-------------------------------------------------------
>
> Comment(by bacek):
>
>  Ok, this is problem with VTABLEs. Replacing {{{ $S0 = $P0 }}} with {{{ $S0
>  = $P0.'get_string'() }}} produces correct results.
>
> --
> Ticket URL: <https://trac.parrot.org/parrot/ticket/944#comment:2>
> Parrot <https://trac.parrot.org/parrot/>
> Parrot Development
> _______________________________________________
> parrot-tickets mailing list
> parrot-tickets@lists.parrot.org
> http://lists.parrot.org/mailman/listinfo/parrot-tickets
>

See also: http://rt.perl.org/rt3/Ticket/Display.html?id=38432, about
throwing an exception from the 'init' vtable, which also breaks (but
differently)

-- 
Will "Coke" Coleda

Changed 12 years ago by bacek@…

Will Coleda wrote:
> 
> See also: http://rt.perl.org/rt3/Ticket/Display.html?id=38432, about
> throwing an exception from the 'init' vtable, which also breaks (but
> differently)
> 

IIUC Parrot_run_meth_from_c* should create new Context similar to 
Sub.invoke.

-- 
Bacek.

Changed 12 years ago by whiteknight

Okay, this is a well-known problem. Unfortunately we have never agreed on a "good" solution to fix it. Here's the quick rundown:

  • We define an exception handler in the current runloop in the current function (:main in this case)
  • We call a VTABLE on a user-defined object. This calls a PIR override, which calls a new runloop function in C to execute it
  • An exception is thrown in the new "inferior" runloop. The handler that was created in the top runloop (in the :main) is found and executed. Control flow, still in the child runloop, returns to the :main function and continues executing till the end of the program.
  • The child runloop exits. Control flow returns back to the parent runloop, and continues executing as if no exception was thrown.

There are several tickets relating to this issue, maybe we should merge some of them together.

Changed 12 years ago by NotFound

Use unroll:

.sub main :main
    $P0 = newclass 'Foo'
    $P0 = new ['Foo']
    push_eh catch
    $S0 = $P0
    say "huh?"
    .return()
 catch:
    .get_results($P1)
    unroll $P1
    say "caught"
    .return()
.end

.namespace ['Foo']

.sub get_string :vtable :method
    $P0 = new ['Exception']
    throw $P0
.end

See TT #1635

Changed 11 years ago by whiteknight

  • status changed from new to closed
  • resolution set to fixed

"unroll" has become "finalize", which is now the standard solution for these kinds of situations. With that new op, this example works. Closing ticket.

Note: See TracTickets for help on using tickets.