Skip to content

Commit 866e260

Browse files
panjf2000gopherbot
authored andcommitted
os: only employ sendfile(3ext) on illumos when target is regular file
Fixes #68863 Change-Id: I0ca324137d1f7510bd0b245791fef07d3b5b401a Reviewed-on: https://go-review.googlesource.com/c/go/+/605355 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Carlos Amedee <[email protected]> Run-TryBot: Andy Pan <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 1416ceb commit 866e260

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

src/os/readfrom_unix_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ func TestCopyFile(t *testing.T) {
198198
}
199199
switch runtime.GOOS {
200200
case "illumos", "solaris":
201-
// On SunOS, We rely on File.Stat to get the size of the file,
201+
// On SunOS, We rely on File.Stat to get the size of the source file,
202202
// which doesn't work for pipe.
203203
if hook.called {
204204
t.Fatalf("%s: shouldn't have called the hook with a source of pipe", testName)
@@ -267,7 +267,7 @@ func TestCopyFile(t *testing.T) {
267267
}
268268
switch runtime.GOOS {
269269
case "illumos", "solaris":
270-
// On SunOS, We rely on File.Stat to get the size of the file,
270+
// On SunOS, We rely on File.Stat to get the size of the source file,
271271
// which doesn't work for pipe.
272272
if hook.called {
273273
t.Fatalf("%s: shouldn't have called the hook with a source of pipe", testName)

src/os/zero_copy_solaris.go

+19
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package os
77
import (
88
"internal/poll"
99
"io"
10+
"runtime"
1011
"syscall"
1112
)
1213

@@ -55,6 +56,24 @@ func (f *File) readFrom(r io.Reader) (written int64, handled bool, err error) {
5556
return 0, false, nil
5657
}
5758

59+
// sendfile() on illumos seems to incur intermittent failures when the
60+
// target file is a standard stream (stdout/stderr), we hereby skip any
61+
// character devices conservatively and leave them to generic copy.
62+
// Check out https://go.dev/issue/68863 for more details.
63+
if runtime.GOOS == "illumos" {
64+
fi, err := f.Stat()
65+
if err != nil {
66+
return 0, false, nil
67+
}
68+
st, ok := fi.Sys().(*syscall.Stat_t)
69+
if !ok {
70+
return 0, false, nil
71+
}
72+
if typ := st.Mode & syscall.S_IFMT; typ == syscall.S_IFCHR || typ == syscall.S_IFBLK {
73+
return 0, false, nil
74+
}
75+
}
76+
5877
if remain == 0 {
5978
fi, err := src.Stat()
6079
if err != nil {

0 commit comments

Comments
 (0)