Skip to content

Add read lock to Service.MarshalJSON to prevent data race during state save#189

Open
AnyCPU wants to merge 1 commit intobasecamp:mainfrom
AnyCPU:fix/service_race_1
Open

Add read lock to Service.MarshalJSON to prevent data race during state save#189
AnyCPU wants to merge 1 commit intobasecamp:mainfrom
AnyCPU:fix/service_race_1

Conversation

@AnyCPU
Copy link
Contributor

@AnyCPU AnyCPU commented Feb 13, 2026

MarshalJSON in internal/server/service.go reads s.active, s.rollout, s.rolloutController, s.options, and s.targetOptions without acquiring s.serviceLock. These fields are modified under the lock by UpdateLoadBalancer, SetRolloutSplit, and StopRollout. Since MarshalJSON is called from saveStateSnapshot during live operation (on every deploy, remove, pause, resume, rollout), a concurrent RPC can race with the state save, potentially causing a nil pointer dereference, corrupted output, or silently wrong state persisted to disk.

Fix

Add s.serviceLock.RLock() / defer s.serviceLock.RUnlock() at the top of MarshalJSON. The matching UnmarshalJSON does not need a lock — it is only called during startup via RestoreLastSavedState, before the server accepts connections.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant