From f4db7d15dc4bbae3ac9f0c7c2b249e2a7970a88d Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Thu, 14 Aug 2014 11:01:39 +0400 Subject: [PATCH 1/4] Fix race condition in sending started signal from monitor Signed-off-by: Alexandr Morozov Upstream-commit: 1480168e9f6178e4015aa4dcc035a6963c59f431 Component: engine --- components/engine/daemon/monitor.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/engine/daemon/monitor.go b/components/engine/daemon/monitor.go index f0fb3d384e..e0fdece14e 100644 --- a/components/engine/daemon/monitor.go +++ b/components/engine/daemon/monitor.go @@ -244,10 +244,12 @@ func (m *containerMonitor) callback(command *execdriver.Command) { m.container.State.SetRunning(command.Pid()) - if m.startSignal != nil { - // signal that the process has started + // signal that the process has started + // close channel only if not closed + select { + case <-m.startSignal: + default: close(m.startSignal) - m.startSignal = nil } if err := m.container.ToDisk(); err != nil { From 1b8bad68b3a11bc69ea1abb4b4069c9d953d059d Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Thu, 14 Aug 2014 15:51:31 +0400 Subject: [PATCH 2/4] Fix race between container cleanup and inspect/ps Signed-off-by: Alexandr Morozov Upstream-commit: 93d6adf8a19855edf118d27d0239222f572d8292 Component: engine --- components/engine/daemon/monitor.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/components/engine/daemon/monitor.go b/components/engine/daemon/monitor.go index e0fdece14e..e8940db24c 100644 --- a/components/engine/daemon/monitor.go +++ b/components/engine/daemon/monitor.go @@ -103,8 +103,17 @@ func (m *containerMonitor) Start() error { exitStatus int ) + // this variable indicates that we under container.Lock + underLock := true + // ensure that when the monitor finally exits we release the networking and unmount the rootfs - defer m.Close() + defer func() { + if !underLock { + m.container.Lock() + defer m.container.Unlock() + } + m.Close() + }() // reset the restart count m.container.RestartCount = -1 @@ -136,6 +145,9 @@ func (m *containerMonitor) Start() error { log.Errorf("Error running container: %s", err) } + // here container.Lock is already lost + underLock = false + m.resetMonitor(err == nil && exitStatus == 0) if m.shouldRestart(exitStatus) { From c26305d80881014fa8ea04e54eb1face44a8f75a Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Thu, 14 Aug 2014 19:38:06 +0400 Subject: [PATCH 3/4] Fix race on state serialization Signed-off-by: Alexandr Morozov Upstream-commit: f1975cbc7c5b551e5a206c15f32aef3d51904408 Component: engine --- components/engine/daemon/state.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/components/engine/daemon/state.go b/components/engine/daemon/state.go index ed137b0206..44742b78c9 100644 --- a/components/engine/daemon/state.go +++ b/components/engine/daemon/state.go @@ -1,6 +1,7 @@ package daemon import ( + "encoding/json" "fmt" "sync" "time" @@ -49,6 +50,16 @@ func (s *State) String() string { return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) } +type jState State + +// MarshalJSON for state is needed to avoid race conditions on inspect +func (s *State) MarshalJSON() ([]byte, error) { + s.RLock() + b, err := json.Marshal(jState(*s)) + s.RUnlock() + return b, err +} + func wait(waitChan <-chan struct{}, timeout time.Duration) error { if timeout < 0 { <-waitChan From 0b9e4ed61ec9628c7d9c6dca37ec0904f50cbb65 Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Thu, 14 Aug 2014 21:50:22 +0400 Subject: [PATCH 4/4] Cleanup: Make channels unbuffered Signed-off-by: Alexandr Morozov Upstream-commit: 0d4d7e4a2851c60f768f71a79a78c068fd9dffe8 Component: engine --- components/engine/daemon/monitor.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/engine/daemon/monitor.go b/components/engine/daemon/monitor.go index e8940db24c..1a929656fa 100644 --- a/components/engine/daemon/monitor.go +++ b/components/engine/daemon/monitor.go @@ -58,8 +58,8 @@ func newContainerMonitor(container *Container, policy runconfig.RestartPolicy) * container: container, restartPolicy: policy, timeIncrement: defaultTimeIncrement, - stopChan: make(chan struct{}, 1), - startSignal: make(chan struct{}, 1), + stopChan: make(chan struct{}), + startSignal: make(chan struct{}), } }