aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqmuntal <quimmuntal@gmail.com>2026-03-08 14:18:04 +0100
committerCarlos Amedee <carlos@golang.org>2026-03-20 09:33:51 -0700
commit2b01132c9f903247207cd0ac29cdaf55fdf96885 (patch)
tree6efb549992d39c927970a613ea1bf42c882a6000
parentba8c3d07a7d0a161f6cfcddc31077df1d8f096c0 (diff)
downloadgo-2b01132c9f903247207cd0ac29cdaf55fdf96885.tar.xz
[release-branch.go1.26] 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. Updates #78015 Fixes #78019 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> (cherry picked from commit d3651c588846e1147e5a72f71c133dc8288e1e13) Reviewed-on: https://go-review.googlesource.com/c/go/+/754082 Reviewed-by: Cherry Mui <cherryyz@google.com>
-rw-r--r--src/internal/poll/sendfile_windows.go4
-rw-r--r--src/net/sendfile.go2
-rw-r--r--src/net/sendfile_stub.go2
-rw-r--r--src/net/sendfile_test.go11
-rw-r--r--src/net/sendfile_windows.go3
5 files changed, 21 insertions, 1 deletions
diff --git a/src/internal/poll/sendfile_windows.go b/src/internal/poll/sendfile_windows.go
index 2bdfecf013..e0bb1ae182 100644
--- a/src/internal/poll/sendfile_windows.go
+++ b/src/internal/poll/sendfile_windows.go
@@ -68,8 +68,10 @@ 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) {
+ off := startpos + written
+ o.o.OffsetHigh = uint32(off >> 32)
+ o.o.Offset = uint32(off)
err := syscall.TransmitFile(fd.Sysfd, hsrc, uint32(chunkSize), 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
if err != nil {
return 0, err
diff --git a/src/net/sendfile.go b/src/net/sendfile.go
index 0e0fcc40ff..572c368ae2 100644
--- a/src/net/sendfile.go
+++ b/src/net/sendfile.go
@@ -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.
//
diff --git a/src/net/sendfile_stub.go b/src/net/sendfile_stub.go
index 17d8d5448f..380c590e26 100644
--- a/src/net/sendfile_stub.go
+++ b/src/net/sendfile_stub.go
@@ -8,6 +8,8 @@ package net
import "io"
+var testHookSupportsSendfile func() bool
+
func supportsSendfile() bool {
return false
}
diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go
index 437d181508..60e22bdede 100644
--- a/src/net/sendfile_test.go
+++ b/src/net/sendfile_test.go
@@ -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
diff --git a/src/net/sendfile_windows.go b/src/net/sendfile_windows.go
index 44ddb421a1..58ac8122db 100644
--- a/src/net/sendfile_windows.go
+++ b/src/net/sendfile_windows.go
@@ -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()
}