From a10ba5e47422e649c22a509646a8d76e8be1e5b5 Mon Sep 17 00:00:00 2001 From: Andrew McCabe Date: Tue, 29 Sep 2026 03:58:31 -0400 Subject: [PATCH] pkg/pidhandle: handle ESRCH from openByHandleAt The kernel can return ESRCH in addition to ESTALE from open_by_handle_at when the process no longer exists. Signed-off-by: Andrew McCabe --- pkg/pidhandle/pidhandle_linux.go | 4 +++- pkg/pidhandle/pidhandle_linux_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/pkg/pidhandle/pidhandle_linux.go b/pkg/pidhandle/pidhandle_linux.go index c9e0b6deda..1e3cddfde5 100644 --- a/pkg/pidhandle/pidhandle_linux.go +++ b/pkg/pidhandle/pidhandle_linux.go @@ -127,7 +127,9 @@ func NewPIDHandleFromString(pid int, pidData string) (PIDHandle, error) { defer unix.Close(fd) pidfd, err := openByHandleAt(fd, fh, unix.O_CLOEXEC) if err != nil { - if errors.Is(err, unix.ESTALE) { + // The process is gone: ESTALE once it has been reaped, ESRCH + // while it is being reaped (pidfs_export_open). + if errors.Is(err, unix.ESTALE) || errors.Is(err, unix.ESRCH) { h.normalHandle.pidData = noSuchProcessID return &h, nil } diff --git a/pkg/pidhandle/pidhandle_linux_test.go b/pkg/pidhandle/pidhandle_linux_test.go index 7ddcbcc1aa..b15a3c1915 100644 --- a/pkg/pidhandle/pidhandle_linux_test.go +++ b/pkg/pidhandle/pidhandle_linux_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/sys/unix" ) @@ -151,6 +152,31 @@ func TestNewPIDHandleFromStringWrongPidData(t *testing.T) { } } +func TestNewPIDHandleFromStringProcessGone(t *testing.T) { + // openByHandleAt may report a process that no longer exists with either + // ESTALE or ESRCH; either must leave a handle to a dead process. + for _, openErr := range []error{unix.ESTALE, unix.ESRCH} { + t.Run(openErr.Error(), func(t *testing.T) { + original_openByHandleAt := openByHandleAt + t.Cleanup(func() { + openByHandleAt = original_openByHandleAt + }) + openByHandleAt = func(_ int, _ unix.FileHandle, _ int) (fd int, err error) { + return -1, openErr + } + + h, err := NewPIDHandleFromString(os.Getpid(), nameToHandlePrefix+"254 74657374") + require.NoError(t, err) + defer h.Close() + + alive, err := h.IsAlive() + assert.NoError(t, err) + assert.False(t, alive) + assert.ErrorIs(t, h.Kill(unix.SIGTERM), unix.ESRCH) + }) + } +} + func TestPIDHandlePidfdStartTime(t *testing.T) { h, err := NewPIDHandleFromString(os.Getpid(), "start-time:1234567890") assert.NoError(t, err)