Skip to content

Avoid retaining returned PipeReader channels - #1528

Merged
Andrew Arnott (AArnott) merged 1 commit into
mainfrom
aarnott-fix-pipereader-leak
Aug 31, 2026
Merged

Avoid retaining returned PipeReader channels#1528
Andrew Arnott (AArnott) merged 1 commit into
mainfrom
aarnott-fix-pipereader-leak

Conversation

@AArnott

Copy link
Copy Markdown
Member

Returned PipeReader values were recorded in the inbound request channel map while deserializing RPC responses. Since ResponseSent is not raised on the receiving client, completed readers remained strongly referenced and could cause unbounded memory growth.

Track whether the formatter is deserializing a request or a response, and only associate channels with the inbound request cleanup map for actual requests. Add regression coverage that drains and completes a returned reader, then verifies it can be collected across all supported formatters.

Fixes #1146

Track whether deserialization is handling a request so response channels are not retained in the inbound request cleanup map.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 28, 2026 22:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Fixes a potential unbounded memory growth scenario when RPC methods return PipeReader values by preventing response-deserialized channels from being tracked as inbound request resources, which previously kept completed channels strongly referenced on the client side.

Changes:

  • Track whether the formatter is deserializing a request vs. a response (internal formatter state).
  • Update duplex pipe tracking to associate inbound channels with the cleanup map only during request deserialization.
  • Add a regression test ensuring a returned PipeReader can be drained, completed, and then garbage-collected (across all formatter-specific derived test classes).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
test/StreamJsonRpc.Tests/DuplexPipeMarshalingTests.cs Adds a regression test and a server RPC method returning a PipeReader to validate collection after completion.
src/StreamJsonRpc/Reflection/MessageFormatterDuplexPipeTracker.cs Avoids recording channels into inboundRequestChannelMap when deserializing responses.
src/StreamJsonRpc/Reflection/IJsonRpcFormatterState.cs Introduces an internal state interface to distinguish request vs. response deserialization.
src/StreamJsonRpc/FormatterBase.cs Implements the internal state (DeserializingRequest) and wires it into deserialization tracking.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@AArnott
Andrew Arnott (AArnott) merged commit dcd7897 into main Aug 31, 2026
10 checks passed
@AArnott
Andrew Arnott (AArnott) deleted the aarnott-fix-pipereader-leak branch August 31, 2026 16:45
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.

Memory leak when returning PipeReader

3 participants