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