fix rootlessport flake

When the rootlessport process is started the stdout/stderr are attached
to the podman process. However once everything is setup podman exits and
when the rootlessport process tries to write to stdout it will fail with
SIGPIPE. The code handles this signal and puts /dev/null to stdout and
stderr but this is not robust. I do not understand the exact cause but
sometimes the process is still killed by SIGPIPE. Either go lost the
signal or the process got already killed before the goroutine could
handle it.

Instead of handling SIGPIPE just set /dev/null to stdout and stderr
before podman exits. With this there should be no race and no way to
run into SIGPIPE errors.

[NO TESTS NEEDED]

Fixes #11248

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger 2021-08-18 20:59:37 +02:00
parent a3d8b48fd5
commit 2d0a0c0d29
No known key found for this signature in database
GPG key ID: EB145DD938A3CAF2

View file

@ -20,7 +20,6 @@ import (
"net" "net"
"os" "os"
"os/exec" "os/exec"
"os/signal"
"path/filepath" "path/filepath"
"github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/ns"
@ -106,30 +105,6 @@ func parent() error {
return err return err
} }
exitC := make(chan os.Signal, 1)
defer close(exitC)
go func() {
sigC := make(chan os.Signal, 1)
signal.Notify(sigC, unix.SIGPIPE)
defer func() {
signal.Stop(sigC)
close(sigC)
}()
select {
case s := <-sigC:
if s == unix.SIGPIPE {
if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil {
unix.Dup2(int(f.Fd()), 1) // nolint:errcheck
unix.Dup2(int(f.Fd()), 2) // nolint:errcheck
f.Close()
}
}
case <-exitC:
}
}()
socketDir := filepath.Join(cfg.TmpDir, "rp") socketDir := filepath.Join(cfg.TmpDir, "rp")
err = os.MkdirAll(socketDir, 0700) err = os.MkdirAll(socketDir, 0700)
if err != nil { if err != nil {
@ -251,8 +226,16 @@ outer:
go serve(socket, driver) go serve(socket, driver)
} }
// write and close ReadyFD (convention is same as slirp4netns --ready-fd)
logrus.Info("ready") logrus.Info("ready")
// https://github.com/containers/podman/issues/11248
// Copy /dev/null to stdout and stderr to prevent SIGPIPE errors
if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil {
unix.Dup2(int(f.Fd()), 1) // nolint:errcheck
unix.Dup2(int(f.Fd()), 2) // nolint:errcheck
f.Close()
}
// write and close ReadyFD (convention is same as slirp4netns --ready-fd)
if _, err := readyW.Write([]byte("1")); err != nil { if _, err := readyW.Write([]byte("1")); err != nil {
return err return err
} }