From 6cb6d9cdf1e0303d1c8a06dbbb650752d2868fdb Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Fri, 2 Sep 2016 15:39:22 -0700 Subject: [PATCH] Lock around saving state Prevent interleaving state syncs as it could conceivably lead to empty state files as per #1367 --- client/alloc_runner.go | 7 +++++++ client/task_runner.go | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/client/alloc_runner.go b/client/alloc_runner.go index d79374ef1..ee7ab9c06 100644 --- a/client/alloc_runner.go +++ b/client/alloc_runner.go @@ -66,6 +66,9 @@ type AllocRunner struct { destroyCh chan struct{} destroyLock sync.Mutex waitCh chan struct{} + + // serialize saveAllocRunnerState calls + persistLock sync.Mutex } // allocRunnerState is used to snapshot the state of the alloc runner @@ -179,8 +182,12 @@ func (r *AllocRunner) SaveState() error { } func (r *AllocRunner) saveAllocRunnerState() error { + r.persistLock.Lock() + defer r.persistLock.Unlock() + // Create the snapshot. alloc := r.Alloc() + r.allocLock.Lock() states := alloc.TaskStates allocClientStatus := r.allocClientStatus diff --git a/client/task_runner.go b/client/task_runner.go index 208f2ab25..b68fbeb65 100644 --- a/client/task_runner.go +++ b/client/task_runner.go @@ -69,6 +69,9 @@ type TaskRunner struct { destroyLock sync.Mutex destroyEvent *structs.TaskEvent waitCh chan struct{} + + // serialize SaveState calls + persistLock sync.Mutex } // taskRunnerState is used to snapshot the state of the task runner @@ -186,6 +189,9 @@ func (r *TaskRunner) RestoreState() error { // SaveState is used to snapshot our state func (r *TaskRunner) SaveState() error { + r.persistLock.Lock() + defer r.persistLock.Unlock() + snap := taskRunnerState{ Task: r.task, Version: r.config.Version,