Skip Menu |

This queue is for tickets about the Future-AsyncAwait CPAN distribution.

Report information
The Basics
Id: 124144
Status: resolved
Priority: 0/
Queue: Future-AsyncAwait

People
Owner: Nobody in particular
Requestors: leonerd-cpan [...] leonerd.org.uk
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.13
Fixed in: 0.14



Subject: Can't await twice in the same foreach loop
Simplest test case is foreach my $x ( 0 ) { await $fA; await $fB } on two pending futures. The second await will die during suspend with Cannot suspend a foreach loop on non-lexical iterator at ... -- Paul Evans
Curiously, this only fails on perl 5.24+. It works just fine on the now-supported 5.18 to 5.22 range. I suspect it may have something to do with the fact we save itervar there, but we don't on 5.24+. -- Paul Evans
On Sat Jan 20 09:03:08 2018, PEVANS wrote: Show quoted text
> Curiously, this only fails on perl 5.24+. It works just fine on the > now-supported 5.18 to 5.22 range. I suspect it may have something to > do with the fact we save itervar there, but we don't on 5.24+.
Yup. It was. -- Paul Evans
Subject: rt124144.patch
=== modified file 'lib/Future/AsyncAwait.xs' --- lib/Future/AsyncAwait.xs 2018-01-20 03:23:20 +0000 +++ lib/Future/AsyncAwait.xs 2018-01-20 14:09:54 +0000 @@ -510,6 +510,8 @@ # endif frame->itervar = SvREFCNT_inc(*CxITERVAR(cx)); +#else + SvREFCNT_inc(*CxITERVAR(cx)); #endif if(type == CXt_LOOP_LAZYSV) { @@ -719,6 +721,9 @@ cx = cx_pushblock(frame->type, frame->gimme, PL_stack_sp, PL_savestack_ix); /* don't call cx_pushloop_plain() because it will get this wrong */ cx->blk_loop = frame->loop; +#if HAVE_PERL_VERSION(5, 24, 0) + cx->cx_type |= CXp_FOR_PAD; +#endif #ifdef HAVE_ITERVAR # ifdef USE_ITHREADS === modified file 't/22context-foreach.t' --- t/22context-foreach.t 2018-01-15 18:03:06 +0000 +++ t/22context-foreach.t 2018-01-20 14:09:54 +0000 @@ -97,6 +97,28 @@ is( scalar $fret->get, "end foreach", '$fret now ready after foreach(LAZY SV) loop' ); } +# RT#124144 +{ + my $f1 = Future->new; + my $f2 = Future->new; + + async sub with_foreach_await_twice + { + foreach my $x ( 0 ) { + await $f1; + await $f2; + } + return "awaited twice"; + } + + my $fret = with_foreach_await_twice(); + + $f1->done; + $f2->done; + + is( scalar $fret->get, "awaited twice", '$fret now ready after foreach with two awaits' ); +} + # TODO: # This ought to be a compiletime check. That's hard right now so for now # it's a runtime check
Released -- Paul Evans