diff --git a/internal/linux/eintr.go b/internal/linux/eintr.go new file mode 100644 index 000000000..4b3dd5197 --- /dev/null +++ b/internal/linux/eintr.go @@ -0,0 +1,18 @@ +package linux + +import ( + "errors" + + "golang.org/x/sys/unix" +) + +// retryOnEINTR takes a function that returns an error and calls it +// until the error returned is not EINTR. +func retryOnEINTR(fn func() error) error { + for { + err := fn() + if !errors.Is(err, unix.EINTR) { + return err + } + } +} diff --git a/internal/linux/linux.go b/internal/linux/linux.go new file mode 100644 index 000000000..d5ce74d2a --- /dev/null +++ b/internal/linux/linux.go @@ -0,0 +1,15 @@ +package linux + +import ( + "os" + + "golang.org/x/sys/unix" +) + +// Sendmsg wraps [unix.Sendmsg]. +func Sendmsg(fd int, p, oob []byte, to unix.Sockaddr, flags int) error { + err := retryOnEINTR(func() error { + return unix.Sendmsg(fd, p, oob, to, flags) + }) + return os.NewSyscallError("sendmsg", err) +} diff --git a/libcontainer/utils/cmsg.go b/libcontainer/utils/cmsg.go index 8b63a1295..96aa3ccc9 100644 --- a/libcontainer/utils/cmsg.go +++ b/libcontainer/utils/cmsg.go @@ -21,6 +21,7 @@ import ( "os" "runtime" + "github.com/opencontainers/runc/internal/linux" "golang.org/x/sys/unix" ) @@ -126,10 +127,5 @@ func SendFile(socket *os.File, file *os.File) error { // SendRawFd sends a specific file descriptor over the given AF_UNIX socket. func SendRawFd(socket *os.File, msg string, fd uintptr) error { oob := unix.UnixRights(int(fd)) - for { - err := unix.Sendmsg(int(socket.Fd()), []byte(msg), oob, nil, 0) - if err != unix.EINTR { - return os.NewSyscallError("sendmsg", err) - } - } + return linux.Sendmsg(int(socket.Fd()), []byte(msg), oob, nil, 0) } diff --git a/notify_socket.go b/notify_socket.go index 34c31cc3f..afe818b3a 100644 --- a/notify_socket.go +++ b/notify_socket.go @@ -11,6 +11,7 @@ import ( "strconv" "time" + "github.com/opencontainers/runc/internal/linux" "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" @@ -181,7 +182,7 @@ func sdNotifyBarrier(client *net.UnixConn) error { return err } - // Get the FD for the unix socket file to be able to do perform syscall.Sendmsg. + // Get the FD for the unix socket file to be able to use sendmsg. clientFd, err := client.File() if err != nil { return err @@ -189,9 +190,9 @@ func sdNotifyBarrier(client *net.UnixConn) error { // Send the write end of the pipe along with a BARRIER=1 message. fdRights := unix.UnixRights(int(pipeW.Fd())) - err = unix.Sendmsg(int(clientFd.Fd()), []byte("BARRIER=1"), fdRights, nil, 0) + err = linux.Sendmsg(int(clientFd.Fd()), []byte("BARRIER=1"), fdRights, nil, 0) if err != nil { - return &os.SyscallError{Syscall: "sendmsg", Err: err} + return err } // Close our copy of pipeW.