Add inconditionnal lock in Start/Stop/Kill to avoid races

This commit is contained in:
Guillaume J. Charmes 2013-04-09 09:09:54 -07:00
parent 329f4449dc
commit 7c2b085d1a
3 changed files with 24 additions and 6 deletions

View File

@ -342,6 +342,9 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
} }
func (container *Container) Start() error { func (container *Container) Start() error {
container.State.lock()
defer container.State.unlock()
if container.State.Running { if container.State.Running {
return fmt.Errorf("The container %s is already running.", container.Id) return fmt.Errorf("The container %s is already running.", container.Id)
} }
@ -411,7 +414,6 @@ func (container *Container) Start() error {
// Init the lock // Init the lock
container.waitLock = make(chan struct{}) container.waitLock = make(chan struct{})
container.ToDisk() container.ToDisk()
go container.monitor() go container.monitor()
return nil return nil
@ -544,7 +546,7 @@ func (container *Container) monitor() {
} }
func (container *Container) kill() error { func (container *Container) kill() error {
if container.cmd == nil { if !container.State.Running || container.cmd == nil {
return nil return nil
} }
if err := container.cmd.Process.Kill(); err != nil { if err := container.cmd.Process.Kill(); err != nil {
@ -556,13 +558,14 @@ func (container *Container) kill() error {
} }
func (container *Container) Kill() error { func (container *Container) Kill() error {
if !container.State.Running { container.State.lock()
return nil defer container.State.unlock()
}
return container.kill() return container.kill()
} }
func (container *Container) Stop() error { func (container *Container) Stop() error {
container.State.lock()
defer container.State.unlock()
if !container.State.Running { if !container.State.Running {
return nil return nil
} }
@ -571,7 +574,7 @@ func (container *Container) Stop() error {
if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil { if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil {
log.Print(string(output)) log.Print(string(output))
log.Print("Failed to send SIGTERM to the process, force killing") log.Print("Failed to send SIGTERM to the process, force killing")
if err := container.Kill(); err != nil { if err := container.kill(); err != nil {
return err return err
} }
} }

View File

@ -150,6 +150,7 @@ func (runtime *Runtime) Register(container *Container) error {
} }
} }
} }
container.State.initLock()
container.runtime = runtime container.runtime = runtime

View File

@ -2,6 +2,7 @@ package docker
import ( import (
"fmt" "fmt"
"sync"
"time" "time"
) )
@ -10,6 +11,7 @@ type State struct {
Pid int Pid int
ExitCode int ExitCode int
StartedAt time.Time StartedAt time.Time
l *sync.Mutex
} }
// String returns a human-readable description of the state // String returns a human-readable description of the state
@ -32,3 +34,15 @@ func (s *State) setStopped(exitCode int) {
s.Pid = 0 s.Pid = 0
s.ExitCode = exitCode s.ExitCode = exitCode
} }
func (s *State) initLock() {
s.l = &sync.Mutex{}
}
func (s *State) lock() {
s.l.Lock()
}
func (s *State) unlock() {
s.l.Unlock()
}