=== modified file 'lib/Future/AsyncAwait.xs'
--- lib/Future/AsyncAwait.xs 2019-04-18 22:34:47 +0000
+++ lib/Future/AsyncAwait.xs 2019-04-24 14:28:45 +0000
@@ -142,14 +142,11 @@
typedef struct {
SV *awaiting_future; /* the Future that 'await' is currently waiting for */
SV *returning_future; /* the Future that its contining CV will eventually return */
+ COP *curcop; /* value of PL_curcop at suspend time */
SuspendedFrame *frames;
U32 padlen;
SV **padslots;
-
-#ifdef DEBUG
- COP *curcop;
-#endif
} SuspendedState;
#ifdef DEBUG
@@ -1576,16 +1573,10 @@
CV *curcv = find_runcv(0);
CV *origcv = curcv;
- COP *curcop = PL_curcop; /* just for debug printing purposes */
bool defer_mortal_curcv = FALSE;
SuspendedState *state = suspendedstate_get(curcv);
-#ifdef DEBUG
- if(state && state->curcop)
- curcop = state->curcop;
-#endif
-
if(state && state->awaiting_future && CATCH_GET) {
/* If we don't do this we get all the mess that is
*
https://rt.cpan.org/Ticket/Display.html?id=126037
@@ -1593,13 +1584,21 @@
return docatch(pp_await);
}
- TRACEPRINT("ENTER await curcv=%p [%s:%d]\n", curcv, CopFILE(curcop), CopLINE(curcop));
+ if(state && state->curcop)
+ PL_curcop = state->curcop;
+
+ TRACEPRINT("ENTER await curcv=%p [%s:%d]\n", curcv, CopFILE(PL_curcop), CopLINE(PL_curcop));
if(state && state->awaiting_future) {
- if(!SvROK(state->returning_future))
- panic("ARGG we lost state->returning_future\n");
+ if(!SvROK(state->returning_future) || future_is_cancelled(state->returning_future)) {
+ if(!SvROK(state->returning_future)) {
+ GV *gv = CvGV(curcv);
+ if(!CvANON(curcv))
+ warn("Suspended async sub %s::%s lost its returning future", HvNAME(GvSTASH(gv)), GvNAME(gv));
+ else
+ warn("Suspended async sub CODE(0x%p) in package %s lost its returning future", curcv, HvNAME(GvSTASH(gv)));
+ }
- if(future_is_cancelled(state->returning_future)) {
TRACEPRINT(" CANCELLED\n");
PUSHMARK(SP);
@@ -1648,13 +1647,11 @@
if(future_is_ready(f)) {
assert(CvDEPTH(curcv) > 0);
TRACEPRINT(" READY\n");
-#ifdef DEBUG
if(state)
state->curcop = NULL;
-#endif
/* This might throw */
future_get_to_stack(f, GIMME_V);
- TRACEPRINT("LEAVE await curcv=%p [%s:%d]\n", curcv, CopFILE(curcop), CopLINE(curcop));
+ TRACEPRINT("LEAVE await curcv=%p [%s:%d]\n", curcv, CopFILE(PL_curcop), CopLINE(PL_curcop));
return PL_op->op_next;
}
@@ -1674,9 +1671,7 @@
TRACEPRINT(" SUSPEND reuse CV\n");
}
-#ifdef DEBUG
- state->curcop = curcop;
-#endif
+ state->curcop = PL_curcop;
suspendedstate_suspend(state, origcv);
@@ -1699,7 +1694,7 @@
if(!SvWEAKREF(state->returning_future))
sv_rvweaken(state->returning_future);
if(!SvROK(state->returning_future))
- panic("ARGH we lost the ->returning_future\n");
+ panic("ARGH we lost state->returning_future for curcv=%p\n", curcv);
/* For unknown reasons, doing this on perls 5.20 or 5.22 massively breaks
* everything.
@@ -1710,11 +1705,11 @@
#endif
if(!SvROK(state->returning_future))
- panic("ARGH we lost the ->returning_future\n");
+ panic("ARGH we lost state->returning_future for curcv=%p\n", curcv);
if(!SvROK(state->awaiting_future))
- panic("ARGH we lost the ->awaiting_future\n");
+ panic("ARGH we lost state->awaiting_future for curcv=%p\n", curcv);
- TRACEPRINT("LEAVE await curcv=%p [%s:%d]\n", curcv, CopFILE(curcop), CopLINE(curcop));
+ TRACEPRINT("LEAVE await curcv=%p [%s:%d]\n", curcv, CopFILE(PL_curcop), CopLINE(PL_curcop));
return PL_ppaddr[OP_RETURN](aTHX);
}
=== modified file 't/42unresolved.t'
--- t/42unresolved.t 2019-03-21 22:22:45 +0000
+++ t/42unresolved.t 2019-04-24 14:31:04 +0000
@@ -10,6 +10,7 @@
use Future::AsyncAwait;
my $orig_cxstack_ix = Future::AsyncAwait::__cxstack_ix;
+my $file = quotemeta __FILE__;
async sub identity
{
@@ -25,12 +26,47 @@
$x + 1 + [ "a", await identity $f ];
}
-# unresolved
-foreach ( 1 .. 1023 ) {
+# abandoned chain
+{
my $f1 = Future->new;
my $fret = func( $f1, 1, 2 );
undef $fret;
+ pass( 'abandoned chain does not crash' );
+}
+
+# abandoned subsequent (RT129303)
+{
+ my $f1 = Future->new;
+ my $fret = func( $f1, 3, 4 );
+
+ undef $fret;
+
+ my $warnings = "";
+ {
+ local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
+ $f1->done;
+ }
+ pass( 'abandoned subsequent does not crash' );
+ like( $warnings, qr/^Suspended async sub main::func lost its returning future at $file line \d+/,
+ 'warning from attempted resume' );
+}
+
+# abandoned subsequent on anon sub
+{
+ my $f1 = Future->new;
+ my $fret = (async sub { await $f1 })->();
+
+ undef $fret;
+
+ my $warnings = "";
+ {
+ local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
+ $f1->done;
+ }
+ pass( 'abandoned subsequent does not crash' );
+ like( $warnings, qr/^Suspended async sub CODE\(0x[0-9a-f]+\) in package main lost its returning future at $file line \d+/,
+ 'warning from attempted resume' );
}
is( Future::AsyncAwait::__cxstack_ix, $orig_cxstack_ix,