-
Notifications
You must be signed in to change notification settings - Fork 3
Potential promise context lost fix #4583 #4584
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -450,7 +450,19 @@ void ICriticalNotifyCompletion.UnsafeOnCompleted(Action continuation) | |
|
|
||
| void INotifyCompletion.OnCompleted(Action continuation) | ||
| { | ||
| ((ICriticalNotifyCompletion)this).UnsafeOnCompleted(continuation); | ||
| // Mirror TaskAwaiter.OnCompleted: flow ExecutionContext so AsyncLocal | ||
| // values set by the caller survive the await and are restored on the | ||
| // thread that resolves the promise. | ||
| var capturedContext = System.Threading.ExecutionContext.Capture(); | ||
| if (capturedContext == null) | ||
| { | ||
| ((ICriticalNotifyCompletion)this).UnsafeOnCompleted(continuation); | ||
| return; | ||
| } | ||
| ((ICriticalNotifyCompletion)this).UnsafeOnCompleted(() => | ||
| { | ||
| System.Threading.ExecutionContext.Run(capturedContext, s => ((Action)s)(), continuation); | ||
| }); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -1253,6 +1265,18 @@ public void SetStateMachine(IAsyncStateMachine machine) | |
| _stateMachine = machine; | ||
| } | ||
|
|
||
| private void MoveNextWithCapturedContext(System.Threading.ExecutionContext capturedContext) | ||
| { | ||
| if (capturedContext == null) | ||
| { | ||
| _stateMachine.MoveNext(); | ||
| } | ||
| else | ||
| { | ||
| System.Threading.ExecutionContext.Run(capturedContext, s => ((IAsyncStateMachine)s).MoveNext(), _stateMachine); | ||
| } | ||
|
||
| } | ||
|
|
||
| public void AwaitOnCompleted<TAwaiter, TStateMachine>( | ||
| ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
| where TAwaiter : INotifyCompletion | ||
|
|
@@ -1264,18 +1288,26 @@ public void AwaitOnCompleted<TAwaiter, TStateMachine>( | |
| _stateMachine.SetStateMachine(stateMachine); | ||
| } | ||
|
|
||
| awaiter.OnCompleted(() => | ||
| { | ||
| _stateMachine.MoveNext(); | ||
| }); | ||
| // Mirror AsyncTaskMethodBuilder: capture ExecutionContext at the await | ||
| // point and restore it before resuming the state machine so AsyncLocal | ||
| // values flow across the await. | ||
| var capturedContext = System.Threading.ExecutionContext.Capture(); | ||
| awaiter.OnCompleted(() => MoveNextWithCapturedContext(capturedContext)); | ||
|
||
| } | ||
|
|
||
| public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( | ||
| ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
| where TAwaiter : ICriticalNotifyCompletion | ||
| where TStateMachine : IAsyncStateMachine | ||
| { | ||
| AwaitOnCompleted(ref awaiter, ref stateMachine); | ||
| if (_stateMachine == null) | ||
| { | ||
| _stateMachine = stateMachine; | ||
| _stateMachine.SetStateMachine(stateMachine); | ||
| } | ||
|
|
||
| var capturedContext = System.Threading.ExecutionContext.Capture(); | ||
| awaiter.UnsafeOnCompleted(() => MoveNextWithCapturedContext(capturedContext)); | ||
|
||
| } | ||
|
|
||
| public void Start<TStateMachine>(ref TStateMachine stateMachine) | ||
|
|
@@ -1313,6 +1345,18 @@ public void SetStateMachine(IAsyncStateMachine machine) | |
| _stateMachine = machine; | ||
| } | ||
|
|
||
| private void MoveNextWithCapturedContext(System.Threading.ExecutionContext capturedContext) | ||
| { | ||
| if (capturedContext == null) | ||
| { | ||
| _stateMachine.MoveNext(); | ||
| } | ||
| else | ||
| { | ||
| System.Threading.ExecutionContext.Run(capturedContext, s => ((IAsyncStateMachine)s).MoveNext(), _stateMachine); | ||
| } | ||
| } | ||
|
|
||
| public void AwaitOnCompleted<TAwaiter, TStateMachine>( | ||
| ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
| where TAwaiter : INotifyCompletion | ||
|
|
@@ -1324,18 +1368,23 @@ public void AwaitOnCompleted<TAwaiter, TStateMachine>( | |
| _stateMachine.SetStateMachine(stateMachine); | ||
| } | ||
|
|
||
| awaiter.OnCompleted(() => | ||
| { | ||
| _stateMachine.MoveNext(); | ||
| }); | ||
| var capturedContext = System.Threading.ExecutionContext.Capture(); | ||
| awaiter.OnCompleted(() => MoveNextWithCapturedContext(capturedContext)); | ||
| } | ||
|
|
||
| public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( | ||
| ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
| where TAwaiter : ICriticalNotifyCompletion | ||
| where TStateMachine : IAsyncStateMachine | ||
| { | ||
| AwaitOnCompleted(ref awaiter, ref stateMachine); | ||
| if (_stateMachine == null) | ||
| { | ||
| _stateMachine = stateMachine; | ||
| _stateMachine.SetStateMachine(stateMachine); | ||
| } | ||
|
|
||
| var capturedContext = System.Threading.ExecutionContext.Capture(); | ||
| awaiter.UnsafeOnCompleted(() => MoveNextWithCapturedContext(capturedContext)); | ||
|
||
| } | ||
|
|
||
| public void Start<TStateMachine>(ref TStateMachine stateMachine) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.