From cea4dd457c0320ced1bfc3151e34417ee565a6b2 Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Wed, 30 Mar 2016 16:53:34 -0700 Subject: [PATCH] Do not allow overlay destroySandbox() to be interrupted - Concurrent leave/join of one member overlay network can end with the error: "subnet sandbox join failed for "A.B.C.D/MM": error creating vxlan interface: file exists" This happens when the join is processed while the leave has already started. Having the network one member only, the leave resets the once variable for this network subnets and triggers the sandbox destroy for each subnet's vxlan interface, when the n.joinCnt goes to 0. But given the destroySandbox() is not atomic, the join thread can trigger the creation of the vxlan interface in between (given subnet.once was re-initialized) before the leave thread removes the vxlan interface for this subnet. - The fix is to not allow interruptions between the re-initialization of the subnet.once var and consequent vxlan interface removal. Signed-off-by: Alessandro Boch --- libnetwork/drivers/overlay/ov_network.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libnetwork/drivers/overlay/ov_network.go b/libnetwork/drivers/overlay/ov_network.go index 1bf91e3f21..9d118ffb4e 100644 --- a/libnetwork/drivers/overlay/ov_network.go +++ b/libnetwork/drivers/overlay/ov_network.go @@ -149,9 +149,9 @@ func (n *network) joinSubnetSandbox(s *subnet) error { func (n *network) leaveSandbox() { n.Lock() + defer n.Unlock() n.joinCnt-- if n.joinCnt != 0 { - n.Unlock() return } @@ -162,15 +162,14 @@ func (n *network) leaveSandbox() { for _, s := range n.subnets { s.once = &sync.Once{} } - n.Unlock() n.destroySandbox() } +// to be called while holding network lock func (n *network) destroySandbox() { - sbox := n.sandbox() - if sbox != nil { - for _, iface := range sbox.Info().Interfaces() { + if n.sbox != nil { + for _, iface := range n.sbox.Info().Interfaces() { if err := iface.Remove(); err != nil { logrus.Debugf("Remove interface %s failed: %v", iface.SrcName(), err) } @@ -197,8 +196,8 @@ func (n *network) destroySandbox() { } } - sbox.Destroy() - n.setSandbox(nil) + n.sbox.Destroy() + n.sbox = nil } }