From 967917c8b4082aafe1834a5f79067cb179eec383 Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Sat, 31 Oct 2015 23:15:15 -0700 Subject: [PATCH] Fix race in os sandbox sharing There is a race in os sandbox sharing code where two containers which are sharing the os sandbox try to recreate the os sandbox again which might result in destroying the os sandbox and recreating it. Since the os sandbox sharing is happening only for default sandbox, refactored the code to create os sandbox only once inside a `sync.Once` api so that it happens exactly once and gets reused by other containers. Also disabled deleting this os sandbox. Signed-off-by: Jana Radhakrishnan --- libnetwork/controller.go | 24 ++++++++++++++++-------- libnetwork/sandbox.go | 2 +- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libnetwork/controller.go b/libnetwork/controller.go index 77d5e68cbb..3e9d8e9f03 100644 --- a/libnetwork/controller.go +++ b/libnetwork/controller.go @@ -144,6 +144,8 @@ type controller struct { unWatchCh chan *endpoint svcDb map[string]svcMap nmap map[string]*netWatch + defOsSbox osl.Sandbox + sboxOnce sync.Once sync.Mutex } @@ -492,12 +494,6 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S config: containerConfig{}, controller: c, } - // This sandbox may be using an existing osl sandbox, sharing it with another sandbox - var peerSb Sandbox - c.WalkSandboxes(SandboxKeyWalker(&peerSb, sb.Key())) - if peerSb != nil { - sb.osSbox = peerSb.(*sandbox).osSbox - } heap.Init(&sb.endpoints) @@ -507,14 +503,26 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S return nil, err } - c.Lock() + if sb.config.useDefaultSandBox { + c.sboxOnce.Do(func() { + c.defOsSbox, err = osl.NewSandbox(sb.Key(), false) + }) + + if err != nil { + c.sboxOnce = sync.Once{} + return nil, fmt.Errorf("failed to create default sandbox: %v", err) + } + + sb.osSbox = c.defOsSbox + } + if sb.osSbox == nil && !sb.config.useExternalKey { if sb.osSbox, err = osl.NewSandbox(sb.Key(), !sb.config.useDefaultSandBox); err != nil { - c.Unlock() return nil, fmt.Errorf("failed to create new osl sandbox: %v", err) } } + c.Lock() c.sandboxes[sb.id] = sb c.Unlock() defer func() { diff --git a/libnetwork/sandbox.go b/libnetwork/sandbox.go index 96ef4c81a7..d6d0ae43a5 100644 --- a/libnetwork/sandbox.go +++ b/libnetwork/sandbox.go @@ -197,7 +197,7 @@ func (sb *sandbox) Delete() error { // likely not required any more. Drop it. etchosts.Drop(sb.config.hostsPath) - if sb.osSbox != nil { + if sb.osSbox != nil && !sb.config.useDefaultSandBox { sb.osSbox.Destroy() }