This commit addresses 3 critical P0 race conditions and resource leaks in core infrastructure: **P0-1: Discovery Service Goroutine Leak** (service.go:468, 488) - **Problem**: ForceRefresh() and SetSubnet() spawned unbounded goroutines without checking if scan already in progress - **Impact**: Rapid API calls create goroutine explosion, resource exhaustion - **Fix**: - ForceRefresh: Check isScanning before spawning goroutine (lines 470-476) - SetSubnet: Check isScanning, defer scan if already running (lines 491-504) - Both now log when skipping to aid debugging **P0-2: Config Persistence Unlock/Relock Race** (persistence.go:1177-1206) - **Problem**: LoadNodesConfig() unlocked RLock, called SaveNodesConfig (acquires Lock), then relocked - **Impact**: Another goroutine could modify config between unlock/relock, causing migrated data loss - **Fix**: - Copy instance slices while holding RLock to ensure consistency (lines 1189-1194) - Release lock, save copies, then return without relocking (lines 1196-1205) - Prevents TOCTOU vulnerability where migrations could be overwritten **P0-3: Config Watcher Channel Close Race** (watcher.go:19-178) - **Problem**: Stop() used select-check-close pattern vulnerable to concurrent calls - **Impact**: Multiple Stop() calls panic on double-close - **Fix**: - Added sync.Once field stopOnce to ConfigWatcher struct (line 26) - Changed Stop() to use stopOnce.Do() ensuring single execution (lines 175-178) - Removed racy select-based guard All fixes maintain backwards compatibility and add defensive logging for operational visibility. |
||
|---|---|---|
| .. | ||
| config_override.go | ||
| service.go | ||
| service_test.go | ||