From 23d52249fafd8a5162399c3e35fc38060b3b1210 Mon Sep 17 00:00:00 2001 From: Andrea Luzzardi Date: Fri, 3 Apr 2015 16:21:48 -0700 Subject: [PATCH] Fix container update flow. This guarantees that containers get fully updated before being inserted in the node (and returned by .Containers()). Fixes #560 Signed-off-by: Andrea Luzzardi --- cluster/swarm/node.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/cluster/swarm/node.go b/cluster/swarm/node.go index 59f34aefc6..957a3d17fb 100644 --- a/cluster/swarm/node.go +++ b/cluster/swarm/node.go @@ -242,8 +242,7 @@ func (n *node) refreshContainer(ID string, full bool) error { func (n *node) updateContainer(c dockerclient.Container, containers map[string]*cluster.Container, full bool) (map[string]*cluster.Container, error) { var container *cluster.Container - n.Lock() - + n.RLock() if current, exists := n.containers[c.Id]; exists { // The container is already known. container = current @@ -254,13 +253,11 @@ func (n *node) updateContainer(c dockerclient.Container, containers map[string]* } full = true } - - // Update its internal state. - container.Container = c - containers[container.Id] = container - // Release the lock here as the next step is slow. - n.Unlock() + // Trade-off: If updateContainer() is called concurrently for the same + // container, we will end up doing a full refresh twice and the original + // container (containers[container.Id]) will get replaced. + n.RUnlock() // Update ContainerInfo. if full { @@ -273,6 +270,12 @@ func (n *node) updateContainer(c dockerclient.Container, containers map[string]* container.Info.Config.CpuShares = container.Info.Config.CpuShares * 1024.0 / n.Cpus } + // Update its internal state. + n.Lock() + container.Container = c + containers[container.Id] = container + n.Unlock() + return containers, nil }