Skip to content

Commit be9df17

Browse files
committed
Fix stale sandbox from store problem
At times, when checkpointed sandbox from store cannot be cleaned up properly we still retain the sandbox in both the store and in memory. But this sandbox store may not contain important configuration information from docker. So when docker requests a new sandbox, instead of using it as is, reconcile the sandbox state from store with the the configuration information provided by docker. To do this mark the sandbox from store as stub and never reveal it to external searches. When docker requests a new sandbox, update the stub sandbox and clear the stub flag. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
1 parent 05a5a15 commit be9df17

3 files changed

Lines changed: 58 additions & 12 deletions

File tree

controller.go

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ type NetworkController interface {
100100
// SandboxByID returns the Sandbox which has the passed id. If not found, a types.NotFoundError is returned.
101101
SandboxByID(id string) (Sandbox, error)
102102

103+
// SandboxDestroy destroys a sandbox given a container ID
104+
SandboxDestroy(id string) error
105+
103106
// Stop network controller
104107
Stop()
105108
}
@@ -478,21 +481,37 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S
478481
return nil, types.BadRequestErrorf("invalid container ID")
479482
}
480483

481-
var existing Sandbox
482-
look := SandboxContainerWalker(&existing, containerID)
483-
c.WalkSandboxes(look)
484-
if existing != nil {
485-
return nil, types.BadRequestErrorf("container %s is already present: %v", containerID, existing)
484+
var sb *sandbox
485+
c.Lock()
486+
for _, s := range c.sandboxes {
487+
if s.containerID == containerID {
488+
// If not a stub, then we already have a complete sandbox.
489+
if !s.isStub {
490+
c.Unlock()
491+
return nil, types.BadRequestErrorf("container %s is already present: %v", containerID, s)
492+
}
493+
494+
// We already have a stub sandbox from the
495+
// store. Make use of it so that we don't lose
496+
// the endpoints from store but reset the
497+
// isStub flag.
498+
sb = s
499+
sb.isStub = false
500+
break
501+
}
486502
}
503+
c.Unlock()
487504

488505
// Create sandbox and process options first. Key generation depends on an option
489-
sb := &sandbox{
490-
id: stringid.GenerateRandomID(),
491-
containerID: containerID,
492-
endpoints: epHeap{},
493-
epPriority: map[string]int{},
494-
config: containerConfig{},
495-
controller: c,
506+
if sb == nil {
507+
sb = &sandbox{
508+
id: stringid.GenerateRandomID(),
509+
containerID: containerID,
510+
endpoints: epHeap{},
511+
epPriority: map[string]int{},
512+
config: containerConfig{},
513+
controller: c,
514+
}
496515
}
497516

498517
heap.Init(&sb.endpoints)
@@ -547,6 +566,11 @@ func (c *controller) Sandboxes() []Sandbox {
547566

548567
list := make([]Sandbox, 0, len(c.sandboxes))
549568
for _, s := range c.sandboxes {
569+
// Hide stub sandboxes from libnetwork users
570+
if s.isStub {
571+
continue
572+
}
573+
550574
list = append(list, s)
551575
}
552576

@@ -574,6 +598,26 @@ func (c *controller) SandboxByID(id string) (Sandbox, error) {
574598
return s, nil
575599
}
576600

601+
// SandboxDestroy destroys a sandbox given a container ID
602+
func (c *controller) SandboxDestroy(id string) error {
603+
var sb *sandbox
604+
c.Lock()
605+
for _, s := range c.sandboxes {
606+
if s.containerID == id {
607+
sb = s
608+
break
609+
}
610+
}
611+
c.Unlock()
612+
613+
// It is not an error if sandbox is not available
614+
if sb == nil {
615+
return nil
616+
}
617+
618+
return sb.Delete()
619+
}
620+
577621
// SandboxContainerWalker returns a Sandbox Walker function which looks for an existing Sandbox with the passed containerID
578622
func SandboxContainerWalker(out *Sandbox, containerID string) SandboxWalker {
579623
return func(sb Sandbox) bool {

sandbox.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type sandbox struct {
6868
joinLeaveDone chan struct{}
6969
dbIndex uint64
7070
dbExists bool
71+
isStub bool
7172
inDelete bool
7273
sync.Mutex
7374
}

sandbox_store.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ func (c *controller) sandboxCleanup() {
188188
endpoints: epHeap{},
189189
epPriority: map[string]int{},
190190
dbIndex: sbs.dbIndex,
191+
isStub: true,
191192
dbExists: true,
192193
}
193194

0 commit comments

Comments
 (0)