Просмотр исходного кода

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 <mrjana@docker.com>
Jana Radhakrishnan 9 лет назад
Родитель
Сommit
967917c8b4
2 измененных файлов с 17 добавлено и 9 удалено
  1. 16 8
      libnetwork/controller.go
  2. 1 1
      libnetwork/sandbox.go

+ 16 - 8
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() {

+ 1 - 1
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()
 	}