fix(docker): disambiguate self-inflicted ping timeout from daemon refusal - #1097
Conversation
…usal Ping killed a still-running `podman info` at its own hard-coded 10s deadline under CI runner CPU/IO contention (CI run 32065209141, up-provider-podman-rootless-exec), then reported the bare "signal: killed" from that kill as an unqualified "daemon is not reachable" -- indistinguishable from a genuine refusal. This masqueraded as test flakiness; --ginkgo.flake-attempts=2 just re-rolled the same race. Ping, StartPodmanMachine, and the systemctl call in StartRootlessPodmanSocket now route through runCmd (via a new runCmdCombined helper) so a kill caused by our own context deadline is wrapped with ctx.Err(), and pingTimeout is raised from 10s to 30s. runPreflight reports a distinct 'did not respond in time' message when the ping error carries context.DeadlineExceeded, instead of always asserting the daemon is down.
✅ Deploy Preview for devsydev canceled.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe change adds shared command output handling, increases the ping timeout to 30 seconds, makes Podman startup timeouts configurable, and distinguishes Docker daemon timeout errors from other preflight failures. ChangesTimeout error handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This localized change distinguishes slow daemon startup from genuine refusal and extends the ping timeout, with regression coverage and passing checks; no actionable merge-blocking risk remains. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Deploy Preview for images-devsy-sh canceled.
|
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 5 |
| Duplication | -5 |
AI Reviewer: run a review on demand. To trigger the first review automatically, go to your organization or repository integration settings. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
|
@Mergifyio queue |
Merge Queue Status
Waiting for
All conditions
|
Root cause
up-provider-podman-rootless-exec(and its rootful/rootless siblings) intermittently fail with:CI run: https://github.com/devsy-org/devsy/actions/runs/32065209141
This is not a genuinely unreachable daemon:
signal: killedis Go's default error whenexec.Cmd.Cancelkills a process on context cancellation -- never something podman itself emits.Ping(pkg/docker/helper.go) builds itspodman infocommand with a hard-codedcontext.WithTimeout(ctx, 10*time.Second), and the failing run's surrounding log span reportselapsed=10.156166312s-- almost exactly that deadline.podman infowas therefore still running, not refused, when Devsy killed it and declared the daemon down.PingpredatesrunCmd(added in fix: disambiguate signal-killed errors from context cancellation #896 specifically to disambiguate a self-inflicted context-cancel kill from a genuine command failure) and was never migrated onto it, sorunPreflighthad no way to tell "we gave up early" apart from "the daemon said no".Confirmed by reproducing the exact pre-fix code path in isolation: a raw
buildCmd(...).CombinedOutput()on a killed process returns bareerr = "signal: killed"with nocontext.DeadlineExceededattached -- reproducing the CI failure message verbatim.Existing CI mitigations (
--ginkgo.flake-attempts=2, dpkg-lock wait, job/test timeout bumps from #1049) target installation-time races and whole-spec timeouts; none touch this in-process 10s ping deadline, so retrying just re-rolls the same race under sustained CI resource contention.Fix
Ping,StartPodmanMachine, and thesystemctl --user start podman.socketcall inStartRootlessPodmanSocketnow route throughrunCmd(via a newrunCmdCombinedhelper), so a self-inflicted timeout kill is wrapped withctx.Err()anderrors.Is(err, context.DeadlineExceeded)works.pingTimeoutraised from a hard-coded 10s to 30s (still well under the 90s Podman-machine-boot budget).runPreflightnow reports "daemon did not respond in time (it may just be slow to start, not necessarily down)" when the ping error carriescontext.DeadlineExceeded, instead of unconditionally claiming the daemon "is not reachable".Testing
pkg/docker/helper_test.goandpkg/driver/docker/preflight_test.goforce the internal deadlines via overridable package vars and asserterrors.Is(err, context.DeadlineExceeded), plus assert a fast native refusal is not misattributed to a timeout.TestRunPreflight*table tests pass unchanged.go build,gofmt -l, andgo test ./pkg/docker/... ./pkg/driver/docker/...all pass.Summary by CodeRabbit