Skip to content

Commit 17a4b7d

Browse files
committed
Respect IsFlowSuppressed when capturing execution context for suspension.
1 parent 44c1e2b commit 17a4b7d

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ internal struct ExecutionAndSyncBlockStore
3131
public void Push()
3232
{
3333
_thread = Thread.CurrentThread;
34+
// Here we get the execution context for synchronous restoring,
35+
// not for flowing across suspension to potentially another thread.
36+
// Therefore we do not need to worry about IsFlowSuppressed
3437
_previousExecutionCtx = _thread._executionContext;
3538
_previousSyncCtx = _thread._synchronizationContext;
3639
}
@@ -178,6 +181,9 @@ private struct RuntimeAsyncAwaitState
178181
public void CaptureContexts()
179182
{
180183
Thread curThread = Thread.CurrentThreadAssumedInitialized;
184+
// Here we get the execution context for presenting to the notifier,
185+
// not for flowing across suspension to potentially another thread.
186+
// Therefore we do not need to worry about IsFlowSuppressed
181187
ExecutionContext = curThread._executionContext;
182188
SynchronizationContext = curThread._synchronizationContext;
183189
}
@@ -775,10 +781,19 @@ private static ValueTask ValueTaskFromException(Exception ex)
775781
return new ValueTask<T?>(TaskFromException<T>(ex));
776782
}
777783

784+
// Called when capturing execution context for suspension.
778785
[MethodImpl(MethodImplOptions.AggressiveInlining)]
779786
private static ExecutionContext? CaptureExecutionContext()
780787
{
781-
return Thread.CurrentThreadAssumedInitialized._executionContext;
788+
ExecutionContext? executionContext = Thread.CurrentThreadAssumedInitialized._executionContext;
789+
if (executionContext?.m_isFlowSuppressed == true)
790+
{
791+
// 'null' is the internal representation of default execution
792+
// context that contains no variables.
793+
executionContext = null;
794+
}
795+
796+
return executionContext;
782797
}
783798

784799
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -796,6 +811,9 @@ private static void RestoreExecutionContext(ExecutionContext? previousExecCtx)
796811
private static void CaptureContexts(out ExecutionContext? execCtx, out SynchronizationContext? syncCtx)
797812
{
798813
Thread thread = Thread.CurrentThreadAssumedInitialized;
814+
// Here we get the execution context for synchronous restoring,
815+
// not for flowing across suspension to potentially another thread.
816+
// Therefore we do not need to worry about IsFlowSuppressed
799817
execCtx = thread._executionContext;
800818
syncCtx = thread._synchronizationContext;
801819
}

src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public sealed class ExecutionContext : IDisposable, ISerializable
2424

2525
private readonly IAsyncLocalValueMap? m_localValues;
2626
private readonly IAsyncLocal[]? m_localChangeNotifications;
27-
private readonly bool m_isFlowSuppressed;
27+
internal readonly bool m_isFlowSuppressed;
2828
private readonly bool m_isDefault;
2929

3030
private ExecutionContext()

0 commit comments

Comments
 (0)