lock.go: fix another race condition

The previous fix to `consul lock` (commit 6875e8d) didn't completely
eliminate the race that could occur if the lock was acquired around the
same time SIGTERM was received:  It was still possible for
Run() to spawn the process via startChild() after killChild() had
released the shared mutex.

Now, when SIGTERM is received, we acquire a mutex that prevents
spawning a new process and never release it.

We've tested this fix pretty thoroughly and believe it completely
resolves the issue.
This commit is contained in:
Michael S. Fischer 2015-08-31 16:33:09 -07:00
parent 56d2fa4c17
commit 01ec256c7e
1 changed files with 4 additions and 3 deletions

View File

@ -185,7 +185,10 @@ func (c *LockCommand) Run(args []string) int {
goto RELEASE
}
// Kill the child
// Prevent starting a new child. The lock is never released
// after this point.
c.childLock.Lock()
// Kill any existing child
if err := c.killChild(childDone); err != nil {
c.Ui.Error(fmt.Sprintf("%s", err))
}
@ -318,9 +321,7 @@ func (c *LockCommand) startChild(script string, doneCh chan struct{}, passStdin
// on the first attempt.
func (c *LockCommand) killChild(childDone chan struct{}) error {
// Get the child process
c.childLock.Lock()
child := c.child
c.childLock.Unlock()
// If there is no child process (failed to start), we can quit early
if child == nil {