appsec: release the listeners when one of them fails - #4642
Open
hamodywe wants to merge 1 commit into
Open
Conversation
listenAndServe returned as soon as either listener sent an error, skipping the shutdown block entirely. The other listener kept serving, so its port stayed held for the lifetime of the process. Nothing rebinds, so every later reload failed on an address that was still in use, while LAPI carried on answering and the process looked healthy. Shut the server down on the way out instead of only when the tomb dies. A listener that never reaches Serve is not one the server tracks, and so not one Shutdown can release: ServeTLS returns before Serve when the cert fails to load, and the missing key/cert checks return earlier still. The goroutine that opened the listener now closes it. 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.
What and why
listenAndServereturned as soon as either listener sent toserverError, which skipped the shutdown block. The other listener stayed insideServe, so its port was held for the lifetime of the process — and since nothing rebinds, every later reload failed on an address still in use while LAPI kept answering and the process looked healthy. One bad reload poisons all the following ones, which is the permanent death in #4545.The server is now shut down on the way out whichever branch returns.
Second hole in the same function: a listener that never reaches
Serveis not one the server tracks, soShutdowncannot release it either.ServeTLSreturns beforeServewhentls.LoadX509KeyPairfails, and the missing key/cert checks instartServerreturn earlier still. The goroutine that opens a listener now closes it.No retry loop — per @blotus in #4545, the bind is not meant to retry; the assumption that the previous server was already shut down is what was wrong.
Fixes #4545
How it was tested
go test ./pkg/acquisition/modules/appsec/...— the whole package, plus-raceon the new tests:The four new tests are deterministic and need no race window: a socket path whose directory does not exist makes the UDS bind fail while TCP succeeds, and vice versa.
With
run.goreverted and the tests kept, exactly the leak cases fail and the clean-shutdown case still passes:Before the fix, the leak is visible directly:
go vet ./pkg/acquisition/modules/appsec/...clean.make testandmake lintwere not run here (Windows, no containers); the pre-existingpkg/acquisitiondocker config failures and thecloudwatchvet finding reproduce on a pristine tree.Checklist
cscli -o json|rawoutput.AI assistance used: mostly
/kind fix
/area appsec