[ROBO-5747] fix: don't log failed-accept Error on server teardown#126
Open
eduard-dumitru wants to merge 2 commits into
Open
[ROBO-5747] fix: don't log failed-accept Error on server teardown#126eduard-dumitru wants to merge 2 commits into
eduard-dumitru wants to merge 2 commits into
Conversation
Disposing an IpcServer cancels the accept loop; on Linux a parked slot's
pipe can surface as a non-OCE IOException ("Pipe is broken") rather than an
OperationCanceledException, which was logged as "Failed to accept new
connection". Suppress it when cancellation is already requested (genuine
errors still log). Includes a real-pipe, Linux red->green regression test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR reduces teardown noise by preventing IpcServer’s accept loop from reporting “Failed to accept new connection” when the server is already shutting down (cancellation requested), and adds a regression test to validate the behavior using real named pipes.
Changes:
- Suppress
_newConnection.OnError(ex)during accept-loop teardown when cancellation is already requested. - Add a named-pipe regression test that captures
System.Diagnostics.Traceerror output and asserts teardown does not emit “Failed to accept new connection”.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/UiPath.CoreIpc/Config/IpcServer.cs | Avoid reporting accept-loop exceptions to observers when cancellation is already requested (teardown race). |
| src/UiPath.CoreIpc.Tests/NamedPipeSmokeTests.Teardown.cs | Adds a real named-pipe regression test to ensure server disposal doesn’t log failed-accept errors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Serialize the whole suite ([assembly: CollectionBehavior( DisableTestParallelization = true)]): the teardown test attaches a process-wide Trace listener, unsafe under xUnit's default parallelism. - Wrap the raw NamedPipeClientStream in `using` (exception-safe; the scope-end dispose is still an abrupt OS handle close). - Drop the fixed Task.Delay sleeps: use Timeouts.Short for the re-park, and remove the post-dispose settle (DisposeAsync already awaits the accept-loop teardown, so any OnError has fired by then). Re-verified on Linux (WSL/Debian, net6.0): 10/10 fail without the fix, 10/10 pass with it; passes on Windows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
/azp run CI |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Collaborator
|
Please fix the node.js on Windows/Ubuntu jobs pipeline |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disposing an IpcServer cancels the accept loop; on Linux a parked slot's pipe can surface as a non-OCE IOException ("Pipe is broken") rather than an OperationCanceledException, which was logged as "Failed to accept new connection". Suppress it when cancellation is already requested (genuine errors still log). Includes a real-pipe, Linux red->green regression test.
Test Results (on CI-RobotIntegration-Test)
PR #126 teardown-noise verification — coreipc
IpcServeraccept loopArtifact:
RobotLogs(per build). Search string in Robot.log:Failed to accept new connectionFull line (before fix):
Failed to accept new connection. Ex: System.IO.IOException: Pipe is broken.Robot.logRobot-*.logRobot.logRobot.logRobot-7f2da42b-c12b-4e07-8da5-247649cc0c57.logRobot.logRobot.logHow to verify: open the file in the leg's RobotLogs zip, Find
Failed to accept new connection→before-fix legs hit it thousands of times (jump to the line #s above); fixed Linux/Docker legs return 0 matches.
Noise is Unix-only (Windows = 0 in both), matching the root cause PR #126 guards.
Test Results (on dev machine) — 20 runs per cell (80 total)
Findings
the exact production stack trace (
IOException: Pipe is brokenatNamedPipeServerTransport.AwaitConnection → IpcServer.Accepter.TryAccept). With the fix itpasses on every run. No flakiness in either direction.
cancellation is a clean
OperationCanceledException(already suppressed); the non-OCEIOExceptiononly leaks on the Linux dispose-based cancellation path. This matches theoriginal report, which was Linux.
How the Linux runs were executed
Follow-up — addressed Copilot review (commit
8c52ee4)Three test-only nits from the Copilot review (the fix itself was unchanged):
[assembly: CollectionBehavior(DisableTestParallelization = true)]. The teardown test attaches a process-wideSystem.Diagnostics.Tracelistener, which is unsafe under xUnit's default cross-collection parallelism; serializing removes the hazard entirely.usingon the rawNamedPipeClientStream— exception-safe (no leak ifConnectAsyncthrows); the scope-end dispose is still an abrupt OS handle close.Task.Delaysleeps —Timeouts.Shortfor the slot re-park, and removed the post-dispose settle delay (DisposeAsyncalready awaits the accept-loop teardown, so anyOnErrorhas fired by then).Re-verified with the new timings (Linux WSL/Debian, net6.0): 10/10 fail without the fix, 10/10 pass with it; Windows still passes.