]> Cypherpunks repositories - gostls13.git/commitdiff
os: only employ sendfile(3ext) on illumos when target is regular file
authorAndy Pan <i@andypan.me>
Wed, 14 Aug 2024 01:41:28 +0000 (09:41 +0800)
committerGopher Robot <gobot@golang.org>
Wed, 14 Aug 2024 18:36:17 +0000 (18:36 +0000)
Fixes #68863

Change-Id: I0ca324137d1f7510bd0b245791fef07d3b5b401a
Reviewed-on: https://go-review.googlesource.com/c/go/+/605355
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Run-TryBot: Andy Pan <panjf2000@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/os/readfrom_unix_test.go
src/os/zero_copy_solaris.go

index 966a4e99623c10014eb5fe9b7637149aacf24716..9ed633639a93c22e4b7d5dda7caed1f50a883d19 100644 (file)
@@ -198,7 +198,7 @@ func TestCopyFile(t *testing.T) {
                                }
                                switch runtime.GOOS {
                                case "illumos", "solaris":
-                                       // On SunOS, We rely on File.Stat to get the size of the file,
+                                       // On SunOS, We rely on File.Stat to get the size of the source file,
                                        // which doesn't work for pipe.
                                        if hook.called {
                                                t.Fatalf("%s: shouldn't have called the hook with a source of pipe", testName)
@@ -267,7 +267,7 @@ func TestCopyFile(t *testing.T) {
                                }
                                switch runtime.GOOS {
                                case "illumos", "solaris":
-                                       // On SunOS, We rely on File.Stat to get the size of the file,
+                                       // On SunOS, We rely on File.Stat to get the size of the source file,
                                        // which doesn't work for pipe.
                                        if hook.called {
                                                t.Fatalf("%s: shouldn't have called the hook with a source of pipe", testName)
index 9d9eca1ae7c5b513b5a0a8c085d59f0d74d82a26..9fb659024eac20cac1004b83d94f3a7ab9abe394 100644 (file)
@@ -7,6 +7,7 @@ package os
 import (
        "internal/poll"
        "io"
+       "runtime"
        "syscall"
 )
 
@@ -55,6 +56,24 @@ func (f *File) readFrom(r io.Reader) (written int64, handled bool, err error) {
                return 0, false, nil
        }
 
+       // sendfile() on illumos seems to incur intermittent failures when the
+       // target file is a standard stream (stdout/stderr), we hereby skip any
+       // character devices conservatively and leave them to generic copy.
+       // Check out https://go.dev/issue/68863 for more details.
+       if runtime.GOOS == "illumos" {
+               fi, err := f.Stat()
+               if err != nil {
+                       return 0, false, nil
+               }
+               st, ok := fi.Sys().(*syscall.Stat_t)
+               if !ok {
+                       return 0, false, nil
+               }
+               if typ := st.Mode & syscall.S_IFMT; typ == syscall.S_IFCHR || typ == syscall.S_IFBLK {
+                       return 0, false, nil
+               }
+       }
+
        if remain == 0 {
                fi, err := src.Stat()
                if err != nil {