fix(remoting): add sync.RWMutex protection for global codec map#3437
fix(remoting): add sync.RWMutex protection for global codec map#3437Aias00 wants to merge 4 commits into
Conversation
The global codec map in remoting/codec.go was accessed without any synchronization: RegistryCodec writes and GetCodec reads could race when called from multiple goroutines. While current production code only writes during init(), the public API allows runtime registration, which would cause a Go map concurrent read-write panic. Add sync.RWMutex to protect all map access: - RegistryCodec: Lock/Unlock for writes - GetCodec: RLock/RUnlock for reads This follows the same pattern used throughout the project (e.g., common/extension/registry_type.go, cluster/cluster/interceptor_invoker.go). Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds concurrency safety to the global codec registry and introduces a regression test to exercise concurrent registry access.
Changes:
- Protects the global
codecmap with ansync.RWMutexinRegistryCodec/GetCodec. - Adds
TestConcurrentCodecAccessto concurrently read/write the registry.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| remoting/codec.go | Adds an RWMutex to make codec registry map access safe under concurrency. |
| remoting/codec_test.go | Adds a concurrency-focused test that exercises concurrent reads/writes to the codec registry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func TestConcurrentCodecAccess(t *testing.T) { | ||
| const goroutines = 100 | ||
| var wg sync.WaitGroup | ||
| wg.Add(goroutines * 2) | ||
|
|
||
| // Concurrent writers | ||
| for i := 0; i < goroutines; i++ { | ||
| go func(i int) { | ||
| defer wg.Done() | ||
| RegistryCodec("concurrent-"+string(rune('a'+i%26)), &mockCodec{}) | ||
| }(i) | ||
| } | ||
|
|
||
| // Concurrent readers | ||
| for i := 0; i < goroutines; i++ { | ||
| go func(i int) { | ||
| defer wg.Done() | ||
| GetCodec("concurrent-" + string(rune('a'+i%26))) | ||
| }(i) | ||
| } | ||
|
|
||
| wg.Wait() | ||
| // If we reach here without a panic, the concurrent access is safe. | ||
| } |
| for i := 0; i < goroutines; i++ { | ||
| go func(i int) { | ||
| defer wg.Done() | ||
| RegistryCodec("concurrent-"+string(rune('a'+i%26)), &mockCodec{}) |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #3437 +/- ##
===========================================
+ Coverage 46.76% 53.57% +6.80%
===========================================
Files 295 493 +198
Lines 17172 38394 +21222
===========================================
+ Hits 8031 20569 +12538
- Misses 8287 16172 +7885
- Partials 854 1653 +799 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|



Problem
The global
codecmap inremoting/codec.gohas no synchronization protection:While
RegistryCodecis currently only called duringinit(),GetCodecis called at runtime from multiple goroutines (e.g.,getty_client.go,getty_server.go). The publicRegistryCodecAPI allows runtime registration, which would cause a Go map concurrent read-write panic.Solution
Add
sync.RWMutexto protect all map access:RegistryCodec:Lock/Unlockfor writesGetCodec:RLock/RUnlockfor readsThis follows the same pattern used throughout the project (e.g.,
common/extension/registry_type.go,cluster/cluster/interceptor_invoker.go).Changes
remoting/codec.go: Addsync.RWMutexprotection forcodecmapremoting/codec_test.go: AddTestConcurrentCodecAccesswith 100 goroutines concurrent read/write under-raceTesting
All tests pass with
-raceflag:🤖 Generated with Claude Code