Fix concurrent map read/write panic in configuration map#3216
Fix concurrent map read/write panic in configuration map#3216nitishagar wants to merge 1 commit into
Conversation
The per-command "check for updates" goroutine reads the settings map (via shouldCheckForUpdate) while `config set` concurrently writes and YAML-marshals the same map, causing a "concurrent map read and map write" runtime panic (observed on Windows CI). Make configmap.Map safe for concurrent use with a sync.RWMutex: lock at the exported entry points and keep the recursive helpers lock-free, and have MarshalYAML/MarshalJSON return a deep snapshot so the encoder never iterates the live map. Fixes arduino#3103
4024fa1 to
0befe04
Compare
|
The only failing check here is This change only adds a |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #3216 +/- ##
==========================================
+ Coverage 69.43% 69.49% +0.06%
==========================================
Files 252 252
Lines 19595 19641 +46
==========================================
+ Hits 13606 13650 +44
- Misses 4718 4719 +1
- Partials 1271 1272 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
What
Make
internal/go-configmap.Mapsafe for concurrent use with async.RWMutex.Why
The background "check for updates" goroutine started for every command reads the settings map (
shouldCheckForUpdate→GetBool) whileconfig setconcurrently writes and YAML-marshals the same map. This races the underlying Go map and panics withfatal error: concurrent map read and map write(reported on Windows CI in #3103).How
*sync.RWMutextoMap(a value mutex would be copied by the value-receiver methods and protect nothing) and initialize it inNew().Get/Set/Delete/Merge/AllKeys/Schema/SetKeyTypeSchema/Marshal*/Unmarshal*and thecli.gosetters); keep the recursive helpers lock-free so the top-level lock protects the whole nested tree without deadlocking.MarshalYAML/MarshalJSONreturn a deep snapshot so the encoder never iterates the live map after the lock is released.TestConcurrentAccess(concurrent reader + writer + marshal), which fails under-racewithout the fix.Fixes #3103