fix: Guard the session proxy pool read with the session lock

What does this MR do and why?

Session.proxyHandler read s.proxyPool[serviceName] directly, without holding s.lock. Meanwhile SetProxyPool reassigns the whole s.proxyPool map under the lock, and every other accessor of that map in session/session.go takes the lock first. The proxy lookup in the handler was the one exception, so a request being served could read the map at the same moment SetProxyPool swapped it out.

That is a data race on the proxy pool map, with two concrete consequences:

  • It fails the repo's -race gate: the race detector flags session/session.go on any concurrent proxy request plus pool update.
  • At runtime it can produce a stale read — the handler sees the old (or a half-updated) map, finds no entry, and returns a spurious 404 with "Proxy not found". The error self-heals on retry, which makes it hard to diagnose.

This MR routes the handler's read through a new locked accessor, s.proxy(serviceName), which takes s.lock for the map lookup exactly the way the file's other accessors do. It is a one-line change at the call site plus the small helper; it adds no new locking surface, it just brings the one unguarded read in line with the existing convention.

What's the best way to test this MR?

Run the session package tests with the race detector:

This MR adds TestProxyPoolConcurrentAccessIsRaceFree, which spins up 16 pairs of goroutines that hammer SetProxyPool and proxyHandler (via Handler().ServeHTTP) concurrently against the same session. On main this test fails under -race; with the fix it passes cleanly. A stubPooler returning an empty pool is used so the test exercises the locking path without needing real proxy backends.

What are the relevant issue numbers?

Closes #40019

Edited by Jeston Singh

Merge request reports

Loading
Loading