Kill the docker probe when its wait times out - #47
Merged
Conversation
ImmichImageAvailable started `docker image inspect` and returned false on a 60-second timeout without ending the child. Disposing a Process frees its handles only, so the probe outlived the test that started it and kept running alongside the rest of the suite. Confirmed the semantics with a standalone probe rather than assuming them: a child started the same way and left to Dispose was still present in /proc after the using block exited, and the same child was gone when Kill ran first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #47 +/- ##
========================================
Coverage 43.37% 43.37%
========================================
Files 28 28
Lines 3896 3896
Branches 306 306
========================================
Hits 1690 1690
Misses 2154 2154
Partials 52 52 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Updates the Docker preflight helper used by VerifyTaskTests to ensure a timed-out docker image inspect probe doesn’t leave a stray docker process running during the test suite.
Changes:
- When
WaitForExit(60_000)times out, the probe now attempts toKill(entireProcessTree: true)before returningfalse. - Adds comments explaining why disposal alone is insufficient in this scenario.
Kill signals termination rather than performing it, so the previous commit still returned while the child was alive. A bounded WaitForExit after the kill is what makes the child gone by the time the helper returns. The early return also left the two ReadToEndAsync drains unobserved. The kill closes their pipes, so a bounded WaitAll finishes them, and the AggregateException catch observes a drain that faulted on the closing pipe. Measured the asynchrony rather than reasoning about it: across five trials a killed child was still present in /proc when Kill returned, and gone after the bounded wait in every one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Answers a suppressed Copilot finding raised on the
developtomainpromotion PR #45, on its head0335970. That review carried no inline comment, so the PR read as having nothing outstanding.The finding
Correct. The helper starts
docker image inspectand returnsfalseon a 60-second timeout. Theusingdisposes theProcess, but disposal frees the handles rather than ending the child, so the probe outlives the test that started it and keeps running alongside the rest of the suite.Verified rather than assumed
Process.Disposesemantics are easy to state wrongly, so a standalone probe checked them instead. A child started the same way and left toDisposealone was still present in/procafter theusingblock exited. The same child, killed first, was gone.The fix
Kill(entireProcessTree: true)runs before thefalsereturn. TheInvalidOperationExceptioncatch covers the child exiting between the timeout expiring and the kill landing, which is a real race rather than defensive padding. AWin32Exceptionfrom the kill falls through to the existing catch on the enclosing block, which already returnsfalse.Verification
CSharpier Format,.NET Build,dotnet format style --verify-no-changes: clean, 0 of 57 files, 0 warnings.dotnet husky run: pass.dotnet test: 372 passed, 0 failed, 0 skipped. The zero matters here: the Immich image is present on this host, so the Docker-gated tests ran rather than skipping, which means this helper was actually exercised.