test(leak): grow stack dump dynamically and cover wedged pipeline paths - #29
Merged
Merged
Conversation
- Grow buffer dynamically in fullStackDump until strictly shorter than buffer to prevent silent truncation in runtime.Stack from masking leaks - Filter internal leak check frames in grgGoroutinesInDump - Add requireNoLingeringGoroutines to assert self-unwinding pipelines mid-test - Add TestLeakDetector_GrowsBufferUntilDumpFits proving truncation avoidance - Add TestGoroutineLeak_SearchPipeline_AbandonWithoutDraining - Add TestGoroutineLeak_SearchPipeline_FatalErrorAbandonsRun - Add TestGoroutineLeak_SearchPipeline_PanickingTask - Add TestGoroutineLeak_AggregateChannel_RealPipelineFatalError - Add TestGoroutineLeak_AggregateChannel_RealPipelineCancelled Closes #19
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.
Description
Fixes the silent stack truncation vulnerability in the goroutine leak detector and adds coverage for wedged pipeline and aggregator paths that were previously untested.
Closes #19
Type of Change
[✓] Bug fix (non-breaking change fixing an issue)
[ ] New feature (non-breaking change adding functionality)
[ ] Performance improvement
[ ] Refactoring or code cleanup
[ ] Documentation update
[ ] CI/CD or build workflow change
Key Changes
Growable Stack Dump:
runtime.Stacksilently truncates when the dump exceeds the buffer capacity, returninglen(buf)with no error. A test binary with many live goroutines can easily exceed the previous fixed 128 KiB buffer, causingverifyNoGoroutineLeaksto pass vacuously.fullStackDump()which dynamically doubles the buffer starting from 64 KiB untiln < len(buf), guaranteeing the complete stack dump is captured without truncation.grgGoroutinesInDump(raw string) []stringand filtered internal testing / leak-checking stack frames (fullStackDump,grgGoroutinesInDump,awaitNoGRGGoroutines,requireNoLingeringGoroutines).requireNoLingeringGoroutines(t, what)to assert no grg goroutines remain mid-test while holding an uncancelled context (proving the component self-unwound rather than relying on deferred cancellation).Expanded Test Coverage:
TestLeakDetector_GrowsBufferUntilDumpFits: Proves that when 64 goroutines are parked at depth 64, the dump exceeds 128 KiB and the fixed buffer underreports the count (17 of 64), whilefullStackDump()captures all 64.TestGoroutineLeak_SearchPipeline_AbandonWithoutDraining: Exercises abandon without cancel by reading 1 result fromExecuteContext, abandoning without draining until workers park onresultsCh <- res, then cancelling and asserting all goroutines unwind.TestGoroutineLeak_SearchPipeline_FatalErrorAbandonsRun: Asserts that a fatal error halts dispatch and stops workers without searching all remaining blobs or leaking goroutines.TestGoroutineLeak_SearchPipeline_PanickingTask: Asserts panic containment in a task surfaces as an error fromExecutewithout leaking goroutines.TestGoroutineLeak_AggregateChannel_RealPipelineFatalError: TestsAggregateChanneldriven by a real pipeline where a poisoned blob explodes while the results buffer is full and workers are blocked on sends. AssertsAggregateChanneldrainingresultsChsuccessfully unwinds the pipeline.TestGoroutineLeak_AggregateChannel_RealPipelineCancelled: TestsAggregateChanneldriven by a real pipeline with mid-stream context cancellation, asserting early termination, correct error propagation, and clean pipeline rundown.Verification & Testing
[✓] Ran
go test -v -count=1 ./...[✓] Ran
go test -race -shuffle=on -count=1 ./...[✓] Ran
go vet ./...[✓] Added or updated unit/integration tests
[✓] Tested manually against sample Git repository histories
Checklist
[✓]
gofmtclean[✓] Every new test mutation-checked: reverting fixes makes them fail
[✓] Passes the full race suite with
-shuffle=on