From eb2c7165c740f14884b60060fcc0ef31585f2ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Thu, 8 Oct 2026 22:45:33 +0200 Subject: [PATCH] container: normalize closed CRI pipe read errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/headers/cri/pipe.go | 9 +++++++++ internal/headers/cri/pipe_internal_test.go | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/internal/headers/cri/pipe.go b/internal/headers/cri/pipe.go index 203f8bd9..73491beb 100644 --- a/internal/headers/cri/pipe.go +++ b/internal/headers/cri/pipe.go @@ -159,6 +159,15 @@ func (c *pipeConn) Read(p []byte) (int, error) { } }) if err != nil { + // Control can reject a closed file before invoking the callback. + c.mu.Lock() + closed := c.closed + c.mu.Unlock() + + if closed { + err = os.ErrClosed + } + return 0, err } diff --git a/internal/headers/cri/pipe_internal_test.go b/internal/headers/cri/pipe_internal_test.go index d60ddd9d..a3c11123 100644 --- a/internal/headers/cri/pipe_internal_test.go +++ b/internal/headers/cri/pipe_internal_test.go @@ -280,6 +280,11 @@ func TestPipeConnClose(t *testing.T) { case <-time.After(5 * time.Second): t.Fatal("Close did not release the pipe handle") } + + // A read started after Close must return the same error as a canceled read. + n, err := server.Read(make([]byte, 1)) + require.Zero(t, n) + require.ErrorIs(t, err, os.ErrClosed) } // Both peers write first. On a pipe without buffer, this blocks both writes