diff --git a/core/metrics/cgroups/v1/oom.go b/core/metrics/cgroups/v1/oom.go index b580281a7..c5ecb1e26 100644 --- a/core/metrics/cgroups/v1/oom.go +++ b/core/metrics/cgroups/v1/oom.go @@ -25,6 +25,7 @@ import ( "golang.org/x/sys/unix" cgroups "github.com/containerd/cgroups/v3/cgroup1" + "github.com/containerd/containerd/v2/pkg/sys" "github.com/containerd/log" metrics "github.com/docker/go-metrics" "github.com/prometheus/client_golang/prometheus" @@ -110,16 +111,20 @@ func (o *oomCollector) Close() error { } func (o *oomCollector) start() { - var events [128]unix.EpollEvent + var ( + n int + err error + events [128]unix.EpollEvent + ) for { - n, err := unix.EpollWait(o.fd, events[:], -1) - if err != nil { - if err == unix.EINTR { - continue - } + if err := sys.IgnoringEINTR(func() error { + n, err = unix.EpollWait(o.fd, events[:], -1) + return err + }); err != nil { log.L.WithError(err).Error("cgroups: epoll wait failed, OOM notifications disabled") return } + for i := 0; i < n; i++ { o.process(uintptr(events[i].Fd)) } diff --git a/core/mount/mount_idmapped_linux.go b/core/mount/mount_idmapped_linux.go index 1b06e658a..4fee53e98 100644 --- a/core/mount/mount_idmapped_linux.go +++ b/core/mount/mount_idmapped_linux.go @@ -190,13 +190,9 @@ func getUsernsFD(uidMaps, gidMaps []syscall.SysProcIDMap) (_usernsFD *os.File, r } func pidfdWaitid(pidFD *os.File) error { - for { - err := unix.Waitid(unix.P_PIDFD, int(pidFD.Fd()), nil, unix.WEXITED, nil) - if err == unix.EINTR { - continue - } - return err - } + return sys.IgnoringEINTR(func() error { + return unix.Waitid(unix.P_PIDFD, int(pidFD.Fd()), nil, unix.WEXITED, nil) + }) } var ( diff --git a/pkg/archive/link_freebsd.go b/pkg/archive/link_freebsd.go index 2097db06b..28251e470 100644 --- a/pkg/archive/link_freebsd.go +++ b/pkg/archive/link_freebsd.go @@ -18,13 +18,13 @@ package archive import ( "os" - "syscall" + "github.com/containerd/containerd/v2/pkg/sys" "golang.org/x/sys/unix" ) func link(oldname, newname string) error { - e := ignoringEINTR(func() error { + e := sys.IgnoringEINTR(func() error { return unix.Linkat(unix.AT_FDCWD, oldname, unix.AT_FDCWD, newname, 0) }) if e != nil { @@ -32,51 +32,3 @@ func link(oldname, newname string) error { } return nil } - -// The following contents were copied from Go 1.18.2. -// Use of this source code is governed by the following -// BSD-style license: -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ignoringEINTR makes a function call and repeats it if it returns an -// EINTR error. This appears to be required even though we install all -// signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846. -// Also #20400 and #36644 are issues in which a signal handler is -// installed without setting SA_RESTART. None of these are the common case, -// but there are enough of them that it seems that we can't avoid -// an EINTR loop. -func ignoringEINTR(fn func() error) error { - for { - err := fn() - if err != syscall.EINTR { - return err - } - } -} diff --git a/pkg/oom/v1/v1.go b/pkg/oom/v1/v1.go index c5423314c..09d9ab26d 100644 --- a/pkg/oom/v1/v1.go +++ b/pkg/oom/v1/v1.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/core/runtime" "github.com/containerd/containerd/v2/pkg/oom" "github.com/containerd/containerd/v2/pkg/shim" + "github.com/containerd/containerd/v2/pkg/sys" "github.com/containerd/log" "golang.org/x/sys/unix" ) @@ -67,23 +68,31 @@ func (e *epoller) Close() error { // Run the epoll loop func (e *epoller) Run(ctx context.Context) { - var events [128]unix.EpollEvent + var ( + n int + err error + events [128]unix.EpollEvent + ) for { - select { - case <-ctx.Done(): - e.Close() - return - default: - n, err := unix.EpollWait(e.fd, events[:], -1) - if err != nil { - if err == unix.EINTR { - continue - } - log.G(ctx).WithError(err).Error("cgroups: epoll wait") + err = sys.IgnoringEINTR(func() error { + select { + case <-ctx.Done(): + e.Close() + return ctx.Err() + default: + n, err = unix.EpollWait(e.fd, events[:], -1) + return err } - for i := 0; i < n; i++ { - e.process(ctx, uintptr(events[i].Fd)) + }) + if err != nil { + if err == context.DeadlineExceeded || err == context.Canceled { + return } + log.G(ctx).WithError(err).Error("cgroups: epoll wait") + } + + for i := 0; i < n; i++ { + e.process(ctx, uintptr(events[i].Fd)) } } }