From dfcc5942f152471dd9373afc0750e3f04e0fb111 Mon Sep 17 00:00:00 2001 From: "Justin Terry (VM)" Date: Fri, 1 Feb 2019 10:22:08 -0800 Subject: [PATCH] Fix deadlock in Windows runhcs shim exec Signed-off-by: Justin Terry (VM) --- runtime/v2/runhcs/process.go | 7 +++++-- runtime/v2/runhcs/service.go | 11 +++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/runtime/v2/runhcs/process.go b/runtime/v2/runhcs/process.go index b57d80dae..0e9a6fece 100644 --- a/runtime/v2/runhcs/process.go +++ b/runtime/v2/runhcs/process.go @@ -53,13 +53,17 @@ func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipe relay: pr, waitBlock: make(chan struct{}), } + process.startedWg.Add(1) go waitForProcess(ctx, process, p, s) return process, nil } +// waitForProcess waits for `p` to exit. +// +// The caller of `waitForProcess` MUST have incremented `process.startedWg` to +// synchronize event start/exit publishing. func waitForProcess(ctx context.Context, process *process, p *os.Process, s *service) { pid := uint32(p.Pid) - process.startedWg.Add(1) // Store the default non-exited value for calls to stat process.exit.Store(&processExit{ @@ -121,7 +125,6 @@ func newExecProcess(ctx context.Context, s *service, cid, id string, pr *pipeRel relay: pr, waitBlock: make(chan struct{}), } - process.startedWg.Add(1) // Store the default non-exited value for calls to stat process.exit.Store(&processExit{ diff --git a/runtime/v2/runhcs/service.go b/runtime/v2/runhcs/service.go index f45414093..656add5ed 100644 --- a/runtime/v2/runhcs/service.go +++ b/runtime/v2/runhcs/service.go @@ -682,6 +682,17 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI. } } + // For the exec case increment the startedWg to make sure we publish the + // started event previous to the exit published in `waitForProcess`. + p.startedWg.Add(1) + defer func() { + if err != nil { + // If an exec failure takes place decrement the startedWg so we + // dont get off on counts. + p.startedWg.Done() + } + }() + // ID here is the containerID to exec the process in. err = rhcs.Exec(ctx, r.ID, procConfig, eopts) if err != nil {