Skip to content

Suppress ExecutionContext flow in BeginErrorReadLine#1498

Closed
ericstj wants to merge 3 commits into
modelcontextprotocol:mainfrom
ericstj:suppress-ec-flow-stderr
Closed

Suppress ExecutionContext flow in BeginErrorReadLine#1498
ericstj wants to merge 3 commits into
modelcontextprotocol:mainfrom
ericstj:suppress-ec-flow-stderr

Conversation

@ericstj

@ericstj ericstj commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Process.BeginErrorReadLine() captures the caller's ExecutionContext, causing AsyncLocal values to leak to the background stderr reader thread. This is undesirable—the stderr handler is a long-lived background I/O callback that shouldn't inherit ambient state from whichever call site happened to create the transport.

Wrap BeginErrorReadLine() in ExecutionContext.SuppressFlow() so the stderr reader gets a clean context.

Add a test that sets an AsyncLocal before creating the transport and verifies the stderr callback does NOT see the value.

Process.BeginErrorReadLine() captures the caller's ExecutionContext,
causing AsyncLocal values to leak to the background stderr reader
thread. This is undesirable—the stderr handler is a long-lived
background I/O callback that shouldn't inherit ambient state from
whichever call site happened to create the transport.

Wrap BeginErrorReadLine() in ExecutionContext.SuppressFlow() so the
stderr reader gets a clean context.

Add a test that sets an AsyncLocal before creating the transport and
verifies the stderr callback does NOT see the value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
stephentoub
stephentoub previously approved these changes Apr 3, 2026
@stephentoub

Copy link
Copy Markdown
Contributor

This is reasonable hygiene, but I'm curious if this is solving some problem you found in the tests?

@ericstj

ericstj commented Apr 6, 2026

Copy link
Copy Markdown
Contributor Author

It was a theory explored as part of the flaky test investigation but it didn't change anything with the test results so I spun it off as a different fix.

Comment thread tests/ModelContextProtocol.Tests/Transport/StdioClientTransportTests.cs Outdated
@ericstj ericstj requested a review from halter73 April 7, 2026 16:07

@halter73 halter73 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without a concrete need, I'm going to close this in order keep the code simple. Let me know if I'm making a mistake here. You know how to reach me.

// Suppress ExecutionContext flow so the Process's internal async
// stderr reader thread doesn't capture the caller's ambient context
// (e.g. AsyncLocal values from test infrastructure or HTTP request state).
using (ExecutionContext.SuppressFlow())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is undesirable—the stderr handler is a long-lived background I/O callback that shouldn't inherit ambient state from whichever call site happened to create the transport.

While I kind of agree with this, I also don't want to be muddying every bit of code that kicks off a potentially longish running task with ExecutionContext.SuppressFlow(). And if we do, I would like some clear cut guidance on what counts as a long running thread that shouldn't be allow to hold on to the execution context.

@halter73 halter73 closed this Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants