query_executor: Fixed race between Query.Release() and speculative executions #1684
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.
As described in #1315, there is a race condition when there is more than one concurrent execution (by means of speculative execution) and
Query.Release()
is called after one of them completes.Query.Release()
callsQuery.reset()
, which in turns zeroes the wholeQuery
. Then, after another execution completes, it tries to access metrics, but they are already set to nil by the call toRelease()
, so a segfault is triggered.The solution is quite simple: a ref counter is introduced into the
Query
. It is obviously initially set to 1. Every execution fiber (i.e. every execution goroutine) has the refcount atomically incremented before it is started, and decrements the refcount on completion.Query.Release()
merely decrements the refcount.Query.reset()
is called by whichever goroutine that decrements the refcount to 0.Fixes: #1315