From 09ddbe3bf386566c91bc0d3bef87d371496e66bc Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Wed, 2 Sep 2026 20:28:45 -0400 Subject: [PATCH] Expose executing runtime async continuation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2d49154c-ca79-4797-a271-c5e9f37b54af --- .../CompilerServices/AsyncHelpers.CoreCLR.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs index 8277c404a62c50..f6717927be3f14 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs @@ -153,7 +153,8 @@ internal unsafe ref struct AsyncDispatcherInfo [FieldOffset(0)] public AsyncDispatcherInfo* Next; - // Next continuation the dispatcher will process. + // Next continuation the dispatcher will process. While a continuation + // is executing, this field remains set to that continuation. #if TARGET_64BIT [FieldOffset(8)] #else @@ -963,12 +964,10 @@ private unsafe void DispatchContinuations() while (true) { Debug.Assert(asyncDispatcherInfo.NextContinuation != null); + Continuation curContinuation = asyncDispatcherInfo.NextContinuation; + Continuation? nextContinuation = curContinuation.Next; try { - Continuation curContinuation = asyncDispatcherInfo.NextContinuation; - Continuation? nextContinuation = curContinuation.Next; - asyncDispatcherInfo.NextContinuation = nextContinuation; - Debug.Assert(awaitState.CurrentThread != null); if (curContinuation.TryGetExecutionContext(out ExecutionContext? execContext)) { @@ -989,11 +988,13 @@ private unsafe void DispatchContinuations() refDispatcherInfo = asyncDispatcherInfo.Next; return; } + + asyncDispatcherInfo.NextContinuation = nextContinuation; } catch (Exception ex) { uint unwindedFrames = 1; // Count current frame. - Continuation? handlerContinuation = UnwindToPossibleHandler(asyncDispatcherInfo.NextContinuation, ex, ref unwindedFrames); + Continuation? handlerContinuation = UnwindToPossibleHandler(nextContinuation, ex, ref unwindedFrames); if (handlerContinuation == null) { // Tail of AsyncTaskMethodBuilderT.SetException @@ -1085,11 +1086,9 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags { Debug.Assert(asyncDispatcherInfo.NextContinuation != null); Continuation curContinuation = asyncDispatcherInfo.NextContinuation; + Continuation? nextContinuation = curContinuation.Next; try { - Continuation? nextContinuation = curContinuation.Next; - asyncDispatcherInfo.NextContinuation = nextContinuation; - RuntimeAsyncInstrumentationHelpers.SyncPointCheck(ref asyncDispatcherInfo, flags, curContinuation); Debug.Assert(awaitState.CurrentThread != null); @@ -1117,11 +1116,12 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags } RuntimeAsyncInstrumentationHelpers.CompleteRuntimeAsyncMethod(ref asyncDispatcherInfo, flags, curContinuation); + asyncDispatcherInfo.NextContinuation = nextContinuation; } catch (Exception ex) { uint unwindedFrames = 1; // Count current frame. - Continuation? handlerContinuation = UnwindToPossibleHandler(asyncDispatcherInfo.NextContinuation, ex, ref unwindedFrames); + Continuation? handlerContinuation = UnwindToPossibleHandler(nextContinuation, ex, ref unwindedFrames); if (handlerContinuation == null) { RuntimeAsyncInstrumentationHelpers.UnwindRuntimeAsyncMethodUnhandledException(ref asyncDispatcherInfo, flags, ex, curContinuation, unwindedFrames);