mirror of
https://github.com/docker/compose.git
synced 2026-08-30 13:31:54 +00:00
fix: hold startMx on the start path actually exercised
startMx exists to serialize ContainerStart calls because the engine assigns published ports from ranges non-atomically. It is held by the plan executor's execStartContainer — a nearly dead code path (plans only emit OpStartContainer for paused/dead containers) — and NOT by startServiceContainer, the path every up/start actually runs. The protection is thus inoperative today: concurrent services publishing overlapping port ranges can race in the engine. Take the mutex around the real ContainerStart call and document the contract on the variable. Starts of different services were already serialized per-service (replicas start sequentially); this serializes the API call across services too, matching what the plan engine will do once the start phase converges (#14081). Part of #14074 (section C) / #14081 (lot 0). Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
06f4f9d622
commit
b857135cb9
1 changed files with 9 additions and 2 deletions
|
|
@ -354,7 +354,11 @@ func (s *composeService) createContainer(ctx context.Context, project *types.Pro
|
|||
return ctr, nil
|
||||
}
|
||||
|
||||
// force sequential calls to ContainerStart to prevent race condition in engine assigning ports from ranges
|
||||
// startMx serializes ContainerStart calls across the whole process: the
|
||||
// engine allocates published ports from ranges non-atomically, and two
|
||||
// concurrent starts can be assigned the same port. Every code path calling
|
||||
// ContainerStart on a service container must hold it (the plan executor's
|
||||
// execStartContainer and the imperative startServiceContainer both do).
|
||||
var startMx sync.Mutex
|
||||
|
||||
func (s *composeService) createMobyContainer(ctx context.Context, project *types.Project, service types.ServiceConfig,
|
||||
|
|
@ -603,7 +607,10 @@ func (s *composeService) startServiceContainer(ctx context.Context, project *typ
|
|||
|
||||
eventName := getContainerProgressName(ctr)
|
||||
s.events.On(newEvent(eventName, api.Working, api.StatusStarting))
|
||||
if _, err := s.apiClient().ContainerStart(ctx, ctr.ID, client.ContainerStartOptions{}); err != nil {
|
||||
startMx.Lock()
|
||||
_, err := s.apiClient().ContainerStart(ctx, ctr.ID, client.ContainerStartOptions{})
|
||||
startMx.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue