From laurent.aml at gmail.com Wed Jul 15 15:12:08 2026 From: laurent.aml at gmail.com (Laurent) Date: Wed, 15 Jul 2026 09:12:08 -0400 Subject: Stack corruption with Coro and AE::cv In-Reply-To: References: Message-ID: Here is a possible fix of the root cause (rather than a Perl-level workaround as before). It still works on Perl 5.22 (no regression) and fixes the problem at least on 5.38. Thanks, -------------------------------- Coro/State.xs -------------------------------- index 89beb15..7a156b7 100644 @@ -1284,23 +1284,31 @@ init_perl (pTHX_ struct coro *coro) static void coro_unwind_stacks (pTHX) { if (!IN_DESTRUCT) { - /* restore all saved variables and stuff */ + /* unwind all extra stacks */ + POPSTACK_TO (PL_mainstack); + + /* Unwind the context stack first. dounwind() pops each context frame + * and leaves *that frame's* scope (CX_LEAVE_SCOPE) in order, restoring + * PL_comppad and CvDEPTH between frames. This must happen before any + * blanket LEAVE_SCOPE(0): doing LEAVE_SCOPE(0) up front would process + * inner-frame save-stack entries (e.g. a `local $h{k}` SAVEt_DELETE, or + * SAVEt_CLEARSV) while the pad is still at the innermost frame's depth, + * leaving an outer frame's pad slot PADSTALE -- which corrupts refcounts + * and asserts/segfaults inside Perl_leave_scope on modern perls (seen + * via ->safe_cancel of a thread blocked in a condvar). */ + dounwind (-1); + + /* restore any remaining base-level saved variables and free temporaries */ LEAVE_SCOPE (0); assert (PL_tmps_floor == -1); /* free all temporaries */ FREETMPS; assert (PL_tmps_ix == -1); - - /* unwind all extra stacks */ - POPSTACK_TO (PL_mainstack); - - /* unwind main stack */ - dounwind (-1); } } static void destroy_perl (pTHX_ struct coro *coro)