From 7061a993c5b620d6e68450f1b90f3458bfa1add0 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Wed, 1 Apr 2015 15:30:48 -0700 Subject: [PATCH] Return closed channel if oom notification fails When working with Go channels you must not set it to nil or else the channel will block forever. It will not panic reading from a nil chan but it blocks. The correct way to do this is to create the channel then close it as the correct results to the caller will be returned. Signed-off-by: Michael Crosby --- daemon/execdriver/native/driver.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/daemon/execdriver/native/driver.go b/daemon/execdriver/native/driver.go index 816207ed3..6afd02321 100644 --- a/daemon/execdriver/native/driver.go +++ b/daemon/execdriver/native/driver.go @@ -156,11 +156,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba startCallback(&c.ProcessConfig, pid) } - oomKillNotification, err := cont.NotifyOOM() - if err != nil { - oomKillNotification = nil - logrus.Warnf("Your kernel does not support OOM notifications: %s", err) - } + oom := notifyOnOOM(cont) waitF := p.Wait if nss := cont.Config().Namespaces; !nss.Contains(configs.NEWPID) { // we need such hack for tracking processes with inerited fds, @@ -176,12 +172,24 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba ps = execErr.ProcessState } cont.Destroy() - - _, oomKill := <-oomKillNotification - + _, oomKill := <-oom return execdriver.ExitStatus{ExitCode: utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), OOMKilled: oomKill}, nil } +// notifyOnOOM returns a channel that signals if the container received an OOM notification +// for any process. If it is unable to subscribe to OOM notifications then a closed +// channel is returned as it will be non-blocking and return the correct result when read. +func notifyOnOOM(container libcontainer.Container) <-chan struct{} { + oom, err := container.NotifyOOM() + if err != nil { + logrus.Warnf("Your kernel does not support OOM notifications: %s", err) + c := make(chan struct{}) + close(c) + return c + } + return oom +} + func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*os.ProcessState, error) { return func() (*os.ProcessState, error) { pid, err := p.Pid()