Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit ec5fb41

Browse files
authored
Avoid unnecessarily propagating ExecutionContext in SocketAsyncEngine (#28676)
SocketAsyncEngines are created lazily on-demand. If we happen to create one at a point where there's a non-default ExecutionContext, we end up capturing that context onto the event loop thread, such that all subsequent dispatches capture and restore that ExecutionContext.
1 parent fe0edc4 commit ec5fb41

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ public bool TryCancel()
266266
// we can't pool the object, as ProcessQueue may still have a reference to it, due to
267267
// using a pattern whereby it takes the lock to grab an item, but then releases the lock
268268
// to do further processing on the item that's still in the list.
269-
ThreadPool.QueueUserWorkItem(o => ((AsyncOperation)o).InvokeCallback(allowPooling: false), this);
269+
ThreadPool.UnsafeQueueUserWorkItem(o => ((AsyncOperation)o).InvokeCallback(allowPooling: false), this);
270270
}
271271

272272
Trace("Exit");
@@ -837,7 +837,7 @@ public void HandleEvent(SocketAsyncContext context)
837837

838838
// We just transitioned from Waiting to Processing.
839839
// Spawn a work item to do the actual processing.
840-
ThreadPool.QueueUserWorkItem(s_processingCallback, context);
840+
ThreadPool.UnsafeQueueUserWorkItem(s_processingCallback, context);
841841
}
842842

843843
// Called on the threadpool when data may be available.
@@ -968,7 +968,7 @@ public void ProcessQueue(SocketAsyncContext context)
968968
Debug.Assert(_state == QueueState.Processing);
969969

970970
// Spawn a new work item to continue processing the queue.
971-
ThreadPool.QueueUserWorkItem(s_processingCallback, context);
971+
ThreadPool.UnsafeQueueUserWorkItem(s_processingCallback, context);
972972
}
973973

974974
// At this point, the operation has completed and it's no longer

src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,11 +286,21 @@ private SocketAsyncEngine()
286286
//
287287
// Start the event loop on its own thread.
288288
//
289-
Task.Factory.StartNew(
290-
EventLoop,
291-
CancellationToken.None,
292-
TaskCreationOptions.LongRunning,
293-
TaskScheduler.Default);
289+
bool suppressFlow = !ExecutionContext.IsFlowSuppressed();
290+
try
291+
{
292+
if (suppressFlow) ExecutionContext.SuppressFlow();
293+
Task.Factory.StartNew(
294+
s => ((SocketAsyncEngine)s).EventLoop(),
295+
this,
296+
CancellationToken.None,
297+
TaskCreationOptions.LongRunning,
298+
TaskScheduler.Default);
299+
}
300+
finally
301+
{
302+
if (suppressFlow) ExecutionContext.RestoreFlow();
303+
}
294304
}
295305
catch
296306
{

0 commit comments

Comments
 (0)