From eb68b900bceea69704ddc9fd72b719a5e19a367b Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Tue, 24 Jan 2017 23:24:05 +0000 Subject: [PATCH] Prevent invalid errors from terminate Both Process.Kill() and Process.Wait() can return errors that don't impact the correct behaviour of terminate. Instead of letting these get returned and logged, which causes confusion, silently ignore them. Currently the test needs to be a string test as the errors are private to the runtime packages, so its our only option. This can be seen if init fails during the setns. Signed-off-by: Steven Hartland --- libcontainer/container_linux.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 2e6c83dbe..1d443d19e 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -289,7 +289,7 @@ func (c *linuxContainer) start(process *Process, isInit bool) error { } if err := parent.start(); err != nil { // terminate the process to ensure that it properly is reaped. - if err := parent.terminate(); err != nil { + if err := ignoreTerminateErrors(parent.terminate()); err != nil { logrus.Warn(err) } return newSystemErrorWithCause(err, "starting container process") @@ -315,7 +315,7 @@ func (c *linuxContainer) start(process *Process, isInit bool) error { } for i, hook := range c.config.Hooks.Poststart { if err := hook.Run(s); err != nil { - if err := parent.terminate(); err != nil { + if err := ignoreTerminateErrors(parent.terminate()); err != nil { logrus.Warn(err) } return newSystemErrorWithCausef(err, "running poststart hook %d", i) @@ -1774,3 +1774,20 @@ func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Na return bytes.NewReader(r.Serialize()), nil } + +// ignoreTerminateErrors returns nil if the given err matches an error known +// to indicate that the terminate occurred successfully or err was nil, otherwise +// err is returned unaltered. +func ignoreTerminateErrors(err error) error { + if err == nil { + return nil + } + + // TODO(steve): Update these to none string checks if the runtime exports them. + switch err.Error() { + case "os: process already finished", "exec: Wait was already called": + return nil + default: + return err + } +}