summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2018-10-31 11:43:33 +0100
committerGiuseppe Scrivano <gscrivan@redhat.com>2018-10-31 13:08:23 +0100
commitea50ce6a5915f71e0cf355d2006ad035adf37034 (patch)
tree8157563017e5120afec08d554d74812d538c640d
parentee513cca8612bebfda36e31203ab215aa682e8c0 (diff)
downloadpodman-ea50ce6a5915f71e0cf355d2006ad035adf37034.tar.gz
podman-ea50ce6a5915f71e0cf355d2006ad035adf37034.tar.bz2
podman-ea50ce6a5915f71e0cf355d2006ad035adf37034.zip
rootless: avoid hang on failed slirp4netns
If for any reason slirp4netns fails at startup, podman waits indefinitely. Check every second if the process is still running so that we avoid to hang. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r--libpod/networking_linux.go28
1 files changed, 25 insertions, 3 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 0d9ec2809..863a764e2 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -12,6 +12,7 @@ import (
"strconv"
"strings"
"syscall"
+ "time"
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
@@ -134,12 +135,33 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessSlirpSyncR, syncW)
if err := cmd.Start(); err != nil {
- return errors.Wrapf(err, "failed to start process")
+ return errors.Wrapf(err, "failed to start slirp4netns process")
}
+ defer cmd.Process.Release()
b := make([]byte, 16)
- if _, err := syncR.Read(b); err != nil {
- return errors.Wrapf(err, "failed to read from sync pipe")
+ for {
+ if err := syncR.SetDeadline(time.Now().Add(1 * time.Second)); err != nil {
+ return errors.Wrapf(err, "error setting slirp4netns pipe timeout")
+ }
+ if _, err := syncR.Read(b); err == nil {
+ break
+ } else {
+ if os.IsTimeout(err) {
+ // Check if the process is still running.
+ var status syscall.WaitStatus
+ _, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil)
+ if err != nil {
+ return errors.Wrapf(err, "failed to read slirp4netns process status")
+ }
+ if status.Exited() || status.Signaled() {
+ return errors.New("slirp4netns failed")
+ }
+
+ continue
+ }
+ return errors.Wrapf(err, "failed to read from slirp4netns sync pipe")
+ }
}
return nil
}