Skip to content

Commit c5839cb

Browse files
znullCopilot
andcommitted
Fix pool buffer bypass caused by *os.File WriterTo
On Go 1.26+, *os.File implements WriterTo. When ioCopier's reader is an *os.File (the common case for commandStage), io.CopyBuffer detects WriterTo and calls File.WriteTo instead of using the provided pool buffer. File.WriteTo's sendfile path fails (the dest is not a network connection), so it falls back to genericWriteTo → io.Copy, which allocates a fresh 32KB buffer on every call — defeating the sync.Pool entirely. Fix: wrap the reader in readerOnly{} to strip all interfaces except Read, forcing io.CopyBuffer to use the pool buffer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 22c71ee commit c5839cb

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

pipe/iocopier.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ var copyBufPool = sync.Pool{
2626
},
2727
}
2828

29+
// readerOnly wraps an io.Reader, hiding any other interfaces (such as
30+
// WriterTo) so that io.CopyBuffer is forced to use the provided buffer.
31+
type readerOnly struct{ io.Reader }
32+
2933
func newIOCopier(w io.WriteCloser) *ioCopier {
3034
return &ioCopier{
3135
w: w,
@@ -41,7 +45,13 @@ func (s *ioCopier) Name() string {
4145
func (s *ioCopier) Start(_ context.Context, _ Env, r io.ReadCloser) (io.ReadCloser, error) {
4246
go func() {
4347
bp := copyBufPool.Get().(*[]byte)
44-
_, err := io.CopyBuffer(s.w, r, *bp)
48+
// Strip all interfaces except Read from r so that
49+
// io.CopyBuffer always uses the provided pool buffer.
50+
// Without this, *os.File's WriterTo (added in Go 1.26)
51+
// causes CopyBuffer to call File.WriteTo, which falls
52+
// back to io.Copy with a fresh allocation, bypassing
53+
// the pool entirely.
54+
_, err := io.CopyBuffer(s.w, readerOnly{r}, *bp)
4555
copyBufPool.Put(bp)
4656
// We don't consider `ErrClosed` an error (FIXME: is this
4757
// correct?):

0 commit comments

Comments
 (0)