# New Ticket Created by Bob Rogers # Please include the string: [perl #56458] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=56458 >
Every RetContinuation in the active call chain must be promoted to a full Continuation by the act of taking an explicit continuation, lest the RetContinuation recycle the context on return when we can still return to it afterwards. For some reason, this does not happen in the particular test case added by the attached patch. However, I have been unable to fix it, because the obvious fix (also in the patch) breaks the build (in r28794) rather horribly. So, I'm submitting this ticket for the record, and will continue working on it when I have more time. (If somebody wants to find out for which revision this last worked, that would be a big help. It's possible that this has never worked; I tend to doubt it, but don't bother going back more than three years.) -- Bob Rogers http://rgrjr.dyndns.org/
* t/pmc/exception.t: + Test case to expose a problem with RetContinuation promotion. * src/pmc/continuation.pmc: + This is the obvious fix, but it breaks the build. Diffs between last version checked in and current workfile(s): Index: t/pmc/exception.t =================================================================== --- t/pmc/exception.t (revision 28798) +++ t/pmc/exception.t (working copy) @@ -6,7 +6,7 @@ use warnings; use lib qw( . lib ../lib ../../lib ); use Test::More; -use Parrot::Test tests => 35; +use Parrot::Test tests => 36; =head1 NAME @@ -836,6 +836,68 @@ ok 3 OUTPUT +pir_output_is(<<'CODE', <<'OUTPUT', "taking a continuation promotes RetCs"); +## This test creates a continuation in a inner sub and re-invokes it later. The +## re-invocation signals an error, which is caught by an intermediate sub. +## Returning from the "test" sub the second time failed in r28794; invoking +## parrot with "-D80" shows clearly that the "test" context was being recycled +## prematurely. For some reason, it is necessary to signal the error in order +## to expose the bug. +.sub main :main + .local int redux + .local pmc cont + ## debug 0x80 + redux = 0 + print "calling test\n" + cont = test() + print "back from test\n" + if redux goto done + redux = 1 + print "calling cont\n" + cont() + print "never.\n" +done: + print "done.\n" +.end +.sub test + ## Push a handler around the foo() call. + push_eh handle_errs + print " calling foo\n" + .local pmc cont + cont = foo() + pop_eh + print " returning from test.\n" + .return (cont) +handle_errs: + print " test: caught error\n" + .return (cont) +.end +.sub foo + ## Take a continuation. + .local pmc cont + cont = new 'Continuation' + set_addr cont, over_there + print " returning from foo\n" + .return (cont) +over_there: + print " got over there.\n" + .local pmc ex + ex = new 'Exception' + throw ex +.end +CODE +calling test + calling foo + returning from foo + returning from test. +back from test +calling cont + got over there. + test: caught error +back from test +done. +OUTPUT + # Local Variables: # mode: cperl # cperl-indent-level: 4 Index: src/pmc/continuation.pmc =================================================================== --- src/pmc/continuation.pmc (revision 28798) +++ src/pmc/continuation.pmc (working copy) @@ -178,7 +178,18 @@ VTABLE void set_pointer(void *value) { opcode_t * const pos = (opcode_t *)value; Parrot_cont * const cc = PMC_cont(SELF); + parrot_context_t * const to_ctx = cc->to_ctx; + PMC * const current_cont = to_ctx->current_cont; + /* + * Whenever we capture a continuation, all return continuations + * up the call chain may be reused due to invoking the + * continuation. To avoid that all return continuations are + * converted to true continuations. + */ + if (current_cont) + invalidate_retc_context(INTERP, current_cont); + if (cc->dynamic_state) cc->dynamic_state->refcount--; End of diffs.