runtime/poll: fix race condition in Window's SendFile

The destination of SendFile is a socket, which doesn't support file
offsets. There is no need to keep track of the file offset, and doing
so causes a race between SendFile and Read.

While here, make sure that SendFile tests do call poll.SendFile.

Fixes #78015

Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-race,gotip-linux-amd64-race
Change-Id: I8cce45c0c110e848d9bdbc5ba340b92ca041f0a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/752860
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
This commit is contained in:
qmuntal
2026-03-08 14:18:04 +01:00
committed by Quim Muntal
parent 97d6430458
commit d3651c5888
5 changed files with 19 additions and 1 deletions

View File

@@ -68,8 +68,8 @@ func SendFile(fd *FD, src uintptr, size int64) (written int64, err error, handle
chunkSize = size
}
fd.setOffset(startpos + written)
n, err := fd.execIO('w', func(o *operation) (uint32, error) {
o.setOffset(startpos + written)
err := syscall.TransmitFile(fd.Sysfd, hsrc, uint32(chunkSize), 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
if err != nil {
return 0, err

View File

@@ -12,6 +12,8 @@ import (
"syscall"
)
var testHookSupportsSendfile func() bool
// sendFile copies the contents of r to c using the sendfile
// system call to minimize copies.
//

View File

@@ -8,6 +8,8 @@ package net
import "io"
var testHookSupportsSendfile func() bool
func supportsSendfile() bool {
return false
}

View File

@@ -28,6 +28,16 @@ const (
newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd"
)
func hookSupportsSendfile(t *testing.T) {
if runtime.GOOS == "windows" {
origHook := testHookSupportsSendfile
testHookSupportsSendfile = func() bool { return true }
t.Cleanup(func() {
testHookSupportsSendfile = origHook
})
}
}
// expectSendfile runs f, and verifies that internal/poll.SendFile successfully handles
// a write to wantConn during f's execution.
//
@@ -35,6 +45,7 @@ const (
// expect a call to SendFile.
func expectSendfile(t *testing.T, wantConn Conn, f func()) {
t.Helper()
hookSupportsSendfile(t)
if !supportsSendfile() {
f()
return

View File

@@ -12,5 +12,8 @@ import "internal/syscall/windows"
// https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile
// https://golang.org/issue/73746
func supportsSendfile() bool {
if testHookSupportsSendfile != nil {
return testHookSupportsSendfile()
}
return windows.SupportUnlimitedTransmitFile()
}