From 9e6359b6f7debcf8462e299e708af17934073afd Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Wed, 14 Jun 2017 19:37:44 +0200 Subject: [PATCH] oci: remove busy loop Signed-off-by: Antonio Murdaca --- oci/oci.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/oci/oci.go b/oci/oci.go index 5eb8339e..10ffd8f9 100644 --- a/oci/oci.go +++ b/oci/oci.go @@ -514,13 +514,26 @@ func (r *Runtime) StopContainer(c *Container, timeout int64) error { timeout = 10 } done := make(chan struct{}) + // we could potentially re-use "done" channel to exit the loop on timeout + // but we use another channel "chControl" so that we won't never incur in the + // case the "done" channel is closed in the "default" select case and we also + // reach the timeout in the select below. If that happens we could raise + // a panic closing a closed channel so better be safe and use another new + // channel just to control the loop. + chControl := make(chan struct{}) go func() { for { - // Check if the process is still around - err := unix.Kill(c.state.Pid, 0) - if err == syscall.ESRCH { - close(done) - break + select { + case <-chControl: + return + default: + // Check if the process is still around + err := unix.Kill(c.state.Pid, 0) + if err == syscall.ESRCH { + close(done) + return + } + time.Sleep(100 * time.Millisecond) } } }() @@ -528,6 +541,7 @@ func (r *Runtime) StopContainer(c *Container, timeout int64) error { case <-done: return nil case <-time.After(time.Duration(timeout) * time.Second): + close(chControl) err := unix.Kill(c.state.Pid, syscall.SIGKILL) if err != nil && err != syscall.ESRCH { return fmt.Errorf("failed to kill process: %v", err)