fix: close named pipe descriptor on error path in pipe-bootstrap#23602
fix: close named pipe descriptor on error path in pipe-bootstrap#23602eran132 wants to merge 4 commits into
Conversation
The Run function in command/connect/envoy/pipe-bootstrap opened a file descriptor via os.OpenFile but leaked it when buf.WriteTo(f) returned an error: the error path returned without calling f.Close(). The success path closes the descriptor, so only the WriteTo failure path leaked. Close the descriptor before returning on the WriteTo error path. A deferred close was avoided because the success path already performs an explicit f.Close() with error checking, which would cause a double close. Fixes hashicorp#23256 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a Linux-only test that exercises the buf.WriteTo error path in Run by targeting /dev/full, whose writes always fail with ENOSPC. The test counts /proc/self/fd before and after the call to assert the named pipe descriptor is released on the error path. Verified by reverting the fix: the test fails (one descriptor leaked) without it and passes with it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement Learn more about why HashiCorp requires a CLA and what the CLA includes Have you signed the CLA already but the status is still pending? Recheck it. |
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes a file descriptor leak in Consul’s internal Envoy pipe-bootstrap command by ensuring the named pipe file descriptor is closed on the buf.WriteTo error path, and adds a Linux-only regression test to prevent regressions.
Changes:
- Close the named pipe descriptor when
buf.WriteTo(f)fails inRun. - Add a Linux regression test that triggers the write-error path using
/dev/fulland checks for descriptor leaks via/proc/self/fd.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap.go |
Closes the named pipe FD on the WriteTo failure path to prevent leaks. |
command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap_linux_test.go |
Adds a Linux-only test to exercise the write-error path and assert no FD leak occurs. |
Comments suppressed due to low confidence (1)
command/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap_linux_test.go:46
- In cleanup,
stdinR.Close()ignores the returned error. Consider checking/logging the Close error (even in tests) to avoid masking unexpected failures when restoring/closing stdin.
os.Stdin = stdinR
t.Cleanup(func() {
os.Stdin = origStdin
stdinR.Close()
})
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if _, err := buf.WriteTo(f); err != nil { | ||
| c.UI.Error(err.Error()) | ||
| f.Close() | ||
| return 1 |
| if _, err := stdinW.WriteString("bootstrap-payload"); err != nil { | ||
| t.Fatal(err) | ||
| } | ||
| stdinW.Close() | ||
|
|
Use _ = f.Close() on the buf.WriteTo error path so the intentional ignore is explicit and consistent with Go convention / errcheck expectations. Same treatment for the two stdin pipe Close calls in the regression test. No behavior change. Addresses Copilot review feedback on PR hashicorp#23602. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for the review! Addressed all three points in 02ff00d:
Re-verified in a Linux container — |
Description
Runincommand/connect/envoy/pipe-bootstrap/connect_envoy_pipe-bootstrap.goopens a file descriptor withos.OpenFileand writes the Envoy bootstrap payload into the named pipe viabuf.WriteTo(f). When that write fails, the function returned1without closingf, leaking the descriptor. The success path and theos.OpenFileerror path are both fine — only theWriteTofailure path leaked.This adds an
f.Close()on that error path. I deliberately did not switch todefer f.Close(): the success path already performs an explicitf.Close()with error checking, so a deferred close would result in a double close on the happy path. The targeted fix keeps the existing structure intact.Testing & Reproduction steps
Added a Linux regression test (
connect_envoy_pipe-bootstrap_linux_test.go) that exercises the failure path: it targets/dev/fullas the pipe path (it opens for writing but every write fails withENOSPC), feeds non-empty stdin, and asserts via/proc/self/fdthat no descriptor is leaked onceRunreturns.Verified in a Linux container:
file descriptor leaked on write-error path: 10 open before Run, 11 after.go vetpass.The test is gated to Linux via the
_linux_test.gofilename suffix because it relies on/dev/fulland/proc/self/fd.Links
PR Checklist
PCI review checklist