Wait for ConcurrentLister workers when the bucket listing fails - #8997
Open
arpitjain099 wants to merge 2 commits into
Open
arpitjain099 wants to merge 2 commits into
arpitjain099 wants to merge 2 commits into
Conversation
GetActiveAndPartialBlockIDs returned as soon as bkt.Iter reported an
error, without closing metaChan and without waiting on the errgroup, so
its 64 workers could still be running after it returned.
BaseFetcher.fetchMetadata closes the activeBlocks channel the moment the
lister returns (defer close, right at the call), so a worker still sitting
in its select could send on a closed channel and take the process down:
panic: send on closed channel
github.com/thanos-io/thanos/pkg/block.(*ConcurrentLister).GetActiveAndPartialBlockIDs.func1()
pkg/block/fetcher.go:294
Close metaChan and wait on every path, keeping the Iter error as the one
reported when both fail. Closing also matters on its own: cancelling the
group context does not break a worker out of a metaChan receive, so a
worker parked there would otherwise never be released.
Fixes thanos-io#8996
Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8997 +/- ##
=======================================
Coverage 64.53% 64.54%
=======================================
Files 289 289
Lines 37366 37367 +1
=======================================
+ Hits 24113 24117 +4
+ Misses 11156 11155 -1
+ Partials 2097 2095 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The misspell linter enforces canceling/canceled. Signed-off-by: Arpit Jain <arpitjain099@gmail.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.
Fixes #8996.
The reporter's reading of the error path is right, and it still holds on
main:BaseFetcher.fetchMetadatacloses the channel it passed in as soon as this returns:so a worker still sitting in its
selectcan send on a closed channel, which is the reported stack atfetcher.go:294.This closes
metaChanand waits on every path, with theItererror taking precedence when both fail. The close is worth having for its own sake too: cancelling the group context does not break a worker out of ametaChanreceive, so a worker parked there would never be released.On the test
I first tried to assert on the panic itself and could not make it fire reliably, which is worth explaining rather than hiding. Once the group context is cancelled, a parked worker has both
<-gCtx.Done()and the send ready, and it usually takes theDonebranch; losing that select to the closed channel is exactly the intermittency behind "329 restarts in four days" while another pod ran six days clean. A test built on it would be flaky in whichever direction the scheduler happened to go.So
TestConcurrentLister_WaitsForWorkersOnIterErrorpins the invariant underneath instead: the lister must not return while a worker is still running. It holds one worker insideExistson a gate, fails another block to cancel the group, and asserts the call has not returned while the held worker is in flight. That is deterministic, and it fails onmainfor the right reason:I also tried a goroutine-leak assertion, which does not catch this: in that configuration the workers are parked in the
selectrather than on themetaChanreceive, so they all exit viaDoneand nothing leaks. Mentioning it in case it looks like an obvious thing to have used.Checks
go build,go vet ./pkg/block/andgofmtare clean, and the new test passes with-race.For the package suite I compared like for like, since this checkout has no object-storage credentials: 20 failures before the change and the same 20 after, with the failure sets identical once the timings are stripped. They are all environment (
insufficient s3 test configuration information,googleapi: Error 400: Unknown project id), not this change.I have not reproduced the original panic against a real GCS bucket, so the confirmation that Bucket Web stops restarting is still worth having from the reporter.