plugin/pkg/uniq: fix data race with sync.RWMutex #7707
Merged
+27
−5
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.
Add RWMutex to protect concurrent map access in Set, Unset, and ForEach methods. Change New() to return *U pointer type for proper synchronization.
1. Why is this pull request needed and what does it do?
This PR fixes a data race in
plugin/pkg/uniqthat occurs during reload operations when multiple goroutines concurrently access the internal map without synchronization.Problem: The
Set(),Unset(), andForEach()methods inplugin/pkg/uniqaccess a shared map without proper locking, causing race conditions detected by Go's race detector duringTestReadme.Solution: Added
sync.RWMutexto protect all map operations:Set(): Uses RLock for existence check, then Lock for write with double-check patternUnset(): Uses Lock for safe deletionForEach(): Uses Lock for iteration and modificationNew()to return*Upointer instead ofUvalue for proper synchronizationTesting: All tests pass with
-raceflag enabled, including the previously failingTestReadme.2. Which issues (if any) are related?
#7703
3. Which documentation changes (if any) need to be made?
None. This is an internal package (
plugin/pkg/uniq) with no user-facing documentation.4. Does this introduce a backward incompatible change or deprecation?
Yes, this introduces a breaking change:
New()now returns*Uinstead ofU.Internal compatibility: ✅ All CoreDNS internal usage (
plugin/metricsandplugin/ready) is fully compatible because they use type inference (u := uniq.New()).External impact:⚠️ Third-party plugins using explicit type declarations may be affected:
Since plugin/pkg/uniq is an internal package not intended for external use, I believe this breaking change is acceptable. However, if backward compatibility is required, I can provide alternative solutions (e.g., deprecation period or dual API).