Ver código fonte

Remove the mutexes and use chan instead in order to handle the wait lock

Guillaume J. Charmes 12 anos atrás
pai
commit
329f4449dc
3 arquivos alterados com 13 adições e 32 exclusões
  1. 11 4
      container.go
  2. 2 3
      runtime.go
  3. 0 25
      state.go

+ 11 - 4
container.go

@@ -43,6 +43,8 @@ type Container struct {
 	ptyMaster io.Closer
 	ptyMaster io.Closer
 
 
 	runtime *Runtime
 	runtime *Runtime
+
+	waitLock chan struct{}
 }
 }
 
 
 type Config struct {
 type Config struct {
@@ -406,6 +408,10 @@ func (container *Container) Start() error {
 	// FIXME: save state on disk *first*, then converge
 	// FIXME: save state on disk *first*, then converge
 	// this way disk state is used as a journal, eg. we can restore after crash etc.
 	// this way disk state is used as a journal, eg. we can restore after crash etc.
 	container.State.setRunning(container.cmd.Process.Pid)
 	container.State.setRunning(container.cmd.Process.Pid)
+
+	// Init the lock
+	container.waitLock = make(chan struct{})
+
 	container.ToDisk()
 	container.ToDisk()
 	go container.monitor()
 	go container.monitor()
 	return nil
 	return nil
@@ -522,6 +528,10 @@ func (container *Container) monitor() {
 
 
 	// Report status back
 	// Report status back
 	container.State.setStopped(exitCode)
 	container.State.setStopped(exitCode)
+
+	// Release the lock
+	close(container.waitLock)
+
 	if err := container.ToDisk(); err != nil {
 	if err := container.ToDisk(); err != nil {
 		// FIXME: there is a race condition here which causes this to fail during the unit tests.
 		// FIXME: there is a race condition here which causes this to fail during the unit tests.
 		// If another goroutine was waiting for Wait() to return before removing the container's root
 		// If another goroutine was waiting for Wait() to return before removing the container's root
@@ -588,10 +598,7 @@ func (container *Container) Restart() error {
 
 
 // Wait blocks until the container stops running, then returns its exit code.
 // Wait blocks until the container stops running, then returns its exit code.
 func (container *Container) Wait() int {
 func (container *Container) Wait() int {
-
-	for container.State.Running {
-		container.State.wait()
-	}
+	<-container.waitLock
 	return container.State.ExitCode
 	return container.State.ExitCode
 }
 }
 
 

+ 2 - 3
runtime.go

@@ -116,7 +116,6 @@ func (runtime *Runtime) Load(id string) (*Container, error) {
 	if err := container.FromDisk(); err != nil {
 	if err := container.FromDisk(); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	container.State.initLock()
 	if container.Id != id {
 	if container.Id != id {
 		return container, fmt.Errorf("Container %s is stored at %s", container.Id, id)
 		return container, fmt.Errorf("Container %s is stored at %s", container.Id, id)
 	}
 	}
@@ -136,6 +135,7 @@ func (runtime *Runtime) Register(container *Container) error {
 	}
 	}
 
 
 	// FIXME: if the container is supposed to be running but is not, auto restart it?
 	// FIXME: if the container is supposed to be running but is not, auto restart it?
+	//        if so, then we need to restart monitor and init a new lock
 	// If the container is supposed to be running, make sure of it
 	// If the container is supposed to be running, make sure of it
 	if container.State.Running {
 	if container.State.Running {
 		if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil {
 		if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil {
@@ -152,8 +152,7 @@ func (runtime *Runtime) Register(container *Container) error {
 	}
 	}
 
 
 	container.runtime = runtime
 	container.runtime = runtime
-	// Setup state lock (formerly in newState()
-	container.State.initLock()
+
 	// Attach to stdout and stderr
 	// Attach to stdout and stderr
 	container.stderr = newWriteBroadcaster()
 	container.stderr = newWriteBroadcaster()
 	container.stdout = newWriteBroadcaster()
 	container.stdout = newWriteBroadcaster()

+ 0 - 25
state.go

@@ -2,7 +2,6 @@ package docker
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"sync"
 	"time"
 	"time"
 )
 )
 
 
@@ -11,9 +10,6 @@ type State struct {
 	Pid       int
 	Pid       int
 	ExitCode  int
 	ExitCode  int
 	StartedAt time.Time
 	StartedAt time.Time
-
-	stateChangeLock *sync.Mutex
-	stateChangeCond *sync.Cond
 }
 }
 
 
 // String returns a human-readable description of the state
 // String returns a human-readable description of the state
@@ -29,31 +25,10 @@ func (s *State) setRunning(pid int) {
 	s.ExitCode = 0
 	s.ExitCode = 0
 	s.Pid = pid
 	s.Pid = pid
 	s.StartedAt = time.Now()
 	s.StartedAt = time.Now()
-	s.broadcast()
 }
 }
 
 
 func (s *State) setStopped(exitCode int) {
 func (s *State) setStopped(exitCode int) {
 	s.Running = false
 	s.Running = false
 	s.Pid = 0
 	s.Pid = 0
 	s.ExitCode = exitCode
 	s.ExitCode = exitCode
-	s.broadcast()
-}
-
-func (s *State) initLock() {
-	if s.stateChangeLock == nil {
-		s.stateChangeLock = &sync.Mutex{}
-		s.stateChangeCond = sync.NewCond(s.stateChangeLock)
-	}
-}
-
-func (s *State) broadcast() {
-	s.stateChangeLock.Lock()
-	s.stateChangeCond.Broadcast()
-	s.stateChangeLock.Unlock()
-}
-
-func (s *State) wait() {
-	s.stateChangeLock.Lock()
-	s.stateChangeCond.Wait()
-	s.stateChangeLock.Unlock()
 }
 }