Skip to content

Fix disposed scope on TCP request timeout - #294

Open
Kowjako wants to merge 1 commit into
dotnet:masterfrom
Kowjako:fix/tcp-timeout-disposed-scope
Open

Fix disposed scope on TCP request timeout#294
Kowjako wants to merge 1 commit into
dotnet:masterfrom
Kowjako:fix/tcp-timeout-disposed-scope

Conversation

@Kowjako

@Kowjako Kowjako commented Aug 14, 2026

Copy link
Copy Markdown

Summary

  • Handle TCP request timeouts while the multiplexed cancellation scope is still valid.
  • Keep lifecycle-triggered cancellation silent during graceful server shutdown.
  • Add a regression test that times out a vote request and verifies that the server accepts a subsequent connection.

Root cause

TcpServer.HandleConnection disposed timeoutSource in the per-request finally block and then inspected that scope in the outer OperationCanceledException handler. Because the cancellation source is pooled, CausedByTimeout could access an already disposed source and throw ObjectDisposedException from the async void connection handler.

Implementation

  • Classify and log request timeouts before disposing timeoutSource in TcpServer.cs (lines 134-138).
  • Leave the outer cancellation handler responsible only for silent connection shutdown in TcpServer.cs (line 150).
  • Extend the transport test member with a cancellable vote delay in TransportTestSuite.cs (lines 41 and 128-140).
  • Add a TCP regression test that verifies recovery after the timed-out request in TcpTransportTests.cs (lines 99-119).

Validation

  • git diff --check
  • Build and tests were not run because the repository instructions explicitly prohibit running .NET builds.

@Kowjako
Kowjako marked this pull request as ready for review August 14, 2026 15:52
@sakno sakno added the ai_assisted Bug or PR is produced partially or fully by the AI model (Codex, Claude, etc.) label Aug 16, 2026
@sakno sakno closed this Aug 16, 2026
@sakno sakno reopened this Aug 16, 2026
@sakno

sakno commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

@Kowjako , thanks for your contribution! According to the contribution rules, please change the target branch to develop.

@sakno sakno added the Lib:Cluster DotNext.Net.Cluster library label Aug 16, 2026
{
await ProcessRequestAsync(messageType, protocol, timeoutSource.Token).ConfigureAwait(false);
}
catch (OperationCanceledException e) when (e.CausedByTimeout(timeoutSource))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

try-catch-finally block is redundant at all. You can do the same thing as in GenericServer:

await ProcessRequestAsync(messageType, protocol, timeoutSource.Token).ConfigureAwait(false);
                
// reset cancellation token
await timeoutSource.DisposeAsync().ConfigureAwait(false);
timeoutSource = default;

and leave the existing handler as-is:

catch (OperationCanceledException e)
{
    // if lifecycleToken is canceled then shutdown socket gracefully without logging
    if (e.CausedByTimeout(timeoutSource))
        logger.RequestTimedOut(clientAddress, e);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai_assisted Bug or PR is produced partially or fully by the AI model (Codex, Claude, etc.) Lib:Cluster DotNext.Net.Cluster library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants