fix(api): serialize tracer Stop against GetResult - #4973
Open
envestcc wants to merge 1 commit into
Open
Conversation
The trace timeout watchdog armed by parseTracer calls tracer.Stop from its own goroutine while the goroutine running the trace calls GetResult. geth's StructLogger stores the interruption reason on a plain field: Stop writes l.reason and only then flips the atomic l.interrupt, and GetResult reads l.reason without consulting that atomic. The two therefore overlap with no happens-before edge between them, which the race detector reports on every debug_trace* path that can time out. Wrap the tracer so Stop and GetResult hold a common mutex. Hooks are passed through untouched -- they run on the tracing goroutine and coordinate through l.interrupt, which is already atomic. Surfaced by TestParseTracerDefaultLoggerTimeoutFires under -race. 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.



The race
parseTracerarms a timeout watchdog that callstracer.Stopfrom its own goroutine, while the goroutine running the trace callsGetResult. geth'sStructLoggerstores the interruption reason on a plain field:reasonis written and read without synchronisation, and the atomicinterruptestablishes no happens-before edge for it becauseGetResultnever reads it. Anydebug_trace*request that hits its deadline can trip this.The fix
Wrap the tracer so
StopandGetResulthold a common mutex.Hooksare passed through untouched — they run on the tracing goroutine and coordinate throughl.interrupt, which is already atomic. Nothing in the geth fork is modified.The guard is applied to every branch of
parseTracer(default struct logger, configured struct logger, and named JS/native tracers), since the watchdog covers all of them.Reproduction
TestParseTracerDefaultLoggerTimeoutFiresalready exercises the path; the race detector is what surfaces it, so no new test is needed.On
master(85fd452):With this commit:
Full
./api/package under the same flags:ok, 0 races.Notes
Found while integrating this fix into
rc_2.5.0; opening it separately againstmasterso the branches don't diverge on it.