1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

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

This commit is contained in:
Guillaume J. Charmes 2013-04-09 07:57:59 -07:00
parent 0767916ade
commit 329f4449dc
3 changed files with 13 additions and 32 deletions

View file

@ -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 {
<-container.waitLock
for container.State.Running {
container.State.wait()
}
return container.State.ExitCode return container.State.ExitCode
} }

View file

@ -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()

View file

@ -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()
} }