Fix tier2/live-backfiller crash, race, leaks and cursor-resolver cancellation#820
Draft
sduchesneau wants to merge 5 commits into
Draft
Fix tier2/live-backfiller crash, race, leaks and cursor-resolver cancellation#820sduchesneau wants to merge 5 commits into
sduchesneau wants to merge 5 commits into
Conversation
The InvalidArgument error was built and logged but never returned, so the request fell through to a nil pointer dereference.
The goroutine closing exec output readers on cancellation iterated existingExecOuts while the main loop was still populating it, a fatal concurrent map iteration and write.
errors.Is(context.Canceled, streamErr) never matches a wrapped cancellation, so context.Cause was never substituted.
Close the tier2 client connection on all requestBackProcessing exit paths (it leaked on errors and was closed twice on success), and stop RequestBackProcessing from blocking forever on its result channel after Start has returned on context cancellation.
When the context is cancelled the source shutdown may win the select via src.Terminated(), falling through to the error fallback which emitted an undo-to-LIB signal instead of the context error (#399).
Contributor
Author
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
Five confirmed bugs in the service layer (plus one small contained fix in
pipeline/resolve.go):tier2: panic on nil
Modules(service/tier2.go)The nil-
Modulesguard inProcessRangebuilt and logged anInvalidArgumenterror but was missing thereturn, falling through to a nil pointer dereference onrequest.Modules.Modules. Added thereturn.tier2: concurrent map iteration and write in
GetExecutionPlan(service/tier2.go)The cleanup goroutine iterates
existingExecOutsonctx.Done()while the main loop is still populating the map — a fatal runtime error that kills the whole tier2 process. Both sides now synchronize on a mutex; exec output readers are still closed on cancellation.tier2: reversed
errors.Isarguments (service/tier2.go)errors.Is(context.Canceled, streamErr)never matches wrapped cancellations, socontext.Cause(ctx)(e.g.errShuttingDown) was lost and the wrong gRPC code was returned. Arguments swapped.live back filler: connection and goroutine leaks (
service/live_back_filler.go)requestBackProcessingleaked the tier2 client connection on both error returns (cleanup defer was registered after them) and closed it twice on success.closeFunc/CloseSendare now deferred right after their resources are acquired.RequestBackProcessingblocked forever sending on the unbufferedjobResultchannel onceStarthad returned onctx.Done(). The send now selects onctx.Done(), andStartbuffers the channel (capacity 1).cursor resolver: cancellation converted into undo-to-LIB signal (
pipeline/resolve.go)Fixes Context canceled (shutting down) may cause UNDO signal to be sent #399 residual: on cancellation,
<-src.Terminated()can win the select over<-ctx.Done()and the error fallback then emitted an undo-to-LIB signal instead of propagating the context error. TheTerminatedbranch now checksctx.Err()and returns it.Tests
All new tests were verified to fail against the unfixed code:
TestProcessRange_NilModules— panicked (nil deref) before, returnsInvalidArgumentafter.TestGetExecutionPlan_CancelledContextNoMapRace—WARNING: DATA RACEunder-racebefore, clean after.TestRequestBackProcessing_ConnectionClosed— closeFunc called 0 times on error paths / 2 times on success before; exactly once on every path after.TestRequestBackProcessing_NoGoroutineLeakOnCancel— blocked >5s before, returns immediately after.TestCursorResolver_CancellationDoesNotEmitUndo— gotjunction=#100 (aa)(undo signal) before, alwayscontext.Canceledafter.go test -race ./service/... ./pipeline/...passes.🤖 Generated with Claude Code