Commit 98d02eb
committed
fix(upstream): make managed.Client config access atomic (MCP-770)
The first MCP-770 fix routed Manager-side reads (DiscoverTools, GetStats,
GetTotalToolCount, ListServers) through GetConfig(), but the underlying
hazard is broader: managed.Client.Config is a pointer field that SetConfig
swaps off m.mu (reconcile add path), while it is read concurrently from many
sites that do NOT hold the client's mc.mu — including Client.Connect's
unlocked phase (client.go:197) and detached state-change callback goroutines
(onStateChange, spawned by StateManager.SetError). The CI -race detector
flagged the Connect-vs-SetConfig variant on PR #555's macOS unit job after
the first fix was cherry-picked.
A mutex-guarded accessor can't cover this: most internal readers run while
mc.mu is already held, so routing them through an RLock GetConfig() would
deadlock (sync.RWMutex is not reentrant). Instead make the field itself
lock-free and data-race-free:
- Replace the exported `Config *config.ServerConfig` field with an
unexported `cfg atomic.Pointer[config.ServerConfig]`.
- GetConfig() returns cfg.Load(); SetConfig() does cfg.Store(). Both are
lock-free and safe whether or not mc.mu is held.
- Route every reader through GetConfig() across the managed client, the
upstream Manager, and the supervisor actor pool.
Add TestConnect_ConfigRace: drives AddServerConfig (SetConfig) against
Client.Connect concurrently; trips -race on the old field, green after.
Verified: go test -race ./internal/upstream/... ./internal/runtime/... and
the original CI victims TestHandleUpstreamServers_AddFromRegistry_HappyPath /
_AdminAllowed_WriteOps pass x5 under -race; build + linter clean.
Related: MCP-7701 parent 59efb9c commit 98d02eb
8 files changed
Lines changed: 192 additions & 133 deletions
File tree
- internal
- runtime/supervisor
- upstream
- managed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
211 | 211 | | |
212 | 212 | | |
213 | 213 | | |
214 | | - | |
215 | | - | |
| 214 | + | |
| 215 | + | |
216 | 216 | | |
217 | 217 | | |
218 | 218 | | |
219 | | - | |
| 219 | + | |
220 | 220 | | |
221 | 221 | | |
222 | 222 | | |
| |||
Lines changed: 13 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
218 | 218 | | |
219 | 219 | | |
220 | 220 | | |
221 | | - | |
222 | | - | |
| 221 | + | |
| 222 | + | |
223 | 223 | | |
224 | 224 | | |
225 | 225 | | |
226 | | - | |
| 226 | + | |
227 | 227 | | |
228 | 228 | | |
229 | 229 | | |
| |||
258 | 258 | | |
259 | 259 | | |
260 | 260 | | |
261 | | - | |
262 | | - | |
| 261 | + | |
| 262 | + | |
263 | 263 | | |
264 | 264 | | |
265 | 265 | | |
266 | | - | |
| 266 | + | |
267 | 267 | | |
268 | 268 | | |
269 | 269 | | |
| |||
328 | 328 | | |
329 | 329 | | |
330 | 330 | | |
331 | | - | |
332 | | - | |
333 | | - | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
334 | 334 | | |
335 | 335 | | |
336 | 336 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
309 | 309 | | |
310 | 310 | | |
311 | 311 | | |
312 | | - | |
| 312 | + | |
313 | 313 | | |
314 | 314 | | |
315 | 315 | | |
| |||
0 commit comments