Ver código fonte

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

Guillaume J. Charmes 12 anos atrás
pai
commit
7c2b085d1a
3 arquivos alterados com 24 adições e 6 exclusões
  1. 9 6
      container.go
  2. 1 0
      runtime.go
  3. 14 0
      state.go

+ 9 - 6
container.go

@@ -342,6 +342,9 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
 }
 
 func (container *Container) Start() error {
+	container.State.lock()
+	defer container.State.unlock()
+
 	if container.State.Running {
 		return fmt.Errorf("The container %s is already running.", container.Id)
 	}
@@ -411,7 +414,6 @@ func (container *Container) Start() error {
 
 	// Init the lock
 	container.waitLock = make(chan struct{})
-
 	container.ToDisk()
 	go container.monitor()
 	return nil
@@ -544,7 +546,7 @@ func (container *Container) monitor() {
 }
 
 func (container *Container) kill() error {
-	if container.cmd == nil {
+	if !container.State.Running || container.cmd == nil {
 		return nil
 	}
 	if err := container.cmd.Process.Kill(); err != nil {
@@ -556,13 +558,14 @@ func (container *Container) kill() error {
 }
 
 func (container *Container) Kill() error {
-	if !container.State.Running {
-		return nil
-	}
+	container.State.lock()
+	defer container.State.unlock()
 	return container.kill()
 }
 
 func (container *Container) Stop() error {
+	container.State.lock()
+	defer container.State.unlock()
 	if !container.State.Running {
 		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 {
 		log.Print(string(output))
 		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
 		}
 	}

+ 1 - 0
runtime.go

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

+ 14 - 0
state.go

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