]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[release-branch.go1.20] os: if descriptor is non-blocking, retain that in Fd method
authorIan Lance Taylor <iant@golang.org>
Tue, 16 May 2023 04:50:51 +0000 (21:50 -0700)
committerGopher Robot <gobot@golang.org>
Thu, 18 May 2023 19:37:57 +0000 (19:37 +0000)
For #58408
For #60211
Fixes #60217

Change-Id: I30f5678b46e15121865b19d1c0f82698493fad4e
Reviewed-on: https://go-review.googlesource.com/c/go/+/495079
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
(cherry picked from commit f777726ff073f8066c017649b572bd8c40940a42)
Reviewed-on: https://go-review.googlesource.com/c/go/+/496015
Reviewed-by: Heschi Kreinick <heschi@google.com>
Auto-Submit: Heschi Kreinick <heschi@google.com>

src/internal/syscall/unix/nonblocking.go
src/internal/syscall/unix/nonblocking_js.go
src/internal/syscall/unix/nonblocking_libc.go
src/os/fifo_test.go
src/os/file_unix.go

index a0becd1e01e04d3db393f8562f5e17114c684d06..6c6f0674d66702f58a70021602c5cb9f265309eb 100644 (file)
@@ -19,3 +19,7 @@ func IsNonblock(fd int) (nonblocking bool, err error) {
        }
        return flag&syscall.O_NONBLOCK != 0, nil
 }
+
+func HasNonblockFlag(flag int) bool {
+       return flag&syscall.O_NONBLOCK != 0
+}
index 8ed40f3f9104adcd09159a2e73e949d763a5259c..cfe78c58d8de2c2bac2f173e98a6908aac051b95 100644 (file)
@@ -9,3 +9,7 @@ package unix
 func IsNonblock(fd int) (nonblocking bool, err error) {
        return false, nil
 }
+
+func HasNonblockFlag(flag int) bool {
+       return false
+}
index bff668496236e680aa21772299db9369abc402a5..1310dbf8ce5478f82ace66958a541d50249d555d 100644 (file)
@@ -19,6 +19,10 @@ func IsNonblock(fd int) (nonblocking bool, err error) {
        return flag&syscall.O_NONBLOCK != 0, nil
 }
 
+func HasNonblockFlag(flag int) bool {
+       return flag&syscall.O_NONBLOCK != 0
+}
+
 // Implemented in the syscall package.
 //
 //go:linkname fcntl syscall.fcntl
index de70927961314c2f4e50025482ac4c97cd243178..ca68e82f05da91e64b94a9c01fe0910c24bede51 100644 (file)
@@ -10,6 +10,7 @@ import (
        "bufio"
        "bytes"
        "fmt"
+       "internal/syscall/unix"
        "io"
        "os"
        "path/filepath"
@@ -101,3 +102,52 @@ func TestFifoEOF(t *testing.T) {
                r.Close()
        }
 }
+
+// Issue 60211.
+func TestOpenFileNonBlocking(t *testing.T) {
+       exe, err := os.Executable()
+       if err != nil {
+               t.Skipf("can't find executable: %v", err)
+       }
+       f, err := os.OpenFile(exe, os.O_RDONLY|syscall.O_NONBLOCK, 0666)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer f.Close()
+       nonblock, err := unix.IsNonblock(int(f.Fd()))
+       if err != nil {
+               t.Fatal(err)
+       }
+       if !nonblock {
+               t.Errorf("file opened with O_NONBLOCK but in blocking mode")
+       }
+}
+
+func TestNewFileNonBlocking(t *testing.T) {
+       var p [2]int
+       if err := syscall.Pipe(p[:]); err != nil {
+               t.Fatal(err)
+       }
+       if err := syscall.SetNonblock(p[0], true); err != nil {
+               t.Fatal(err)
+       }
+       f := os.NewFile(uintptr(p[0]), "pipe")
+       nonblock, err := unix.IsNonblock(p[0])
+       if err != nil {
+               t.Fatal(err)
+       }
+       if !nonblock {
+               t.Error("pipe blocking after NewFile")
+       }
+       fd := f.Fd()
+       if fd != uintptr(p[0]) {
+               t.Errorf("Fd returned %d, want %d", fd, p[0])
+       }
+       nonblock, err = unix.IsNonblock(p[0])
+       if err != nil {
+               t.Fatal(err)
+       }
+       if !nonblock {
+               t.Error("pipe blocking after Fd")
+       }
+}
index 1833c26531602b2256e0fa7ad44c1875a5525330..8f531d9a102d68b76e1ec5bd3efb29ade70a1b1b 100644 (file)
@@ -171,7 +171,9 @@ func newFile(fd uintptr, name string, kind newFileKind) *File {
        clearNonBlock := false
        if pollable {
                if kind == kindNonBlock {
-                       f.nonblock = true
+                       // The descriptor is already in non-blocking mode.
+                       // We only set f.nonblock if we put the file into
+                       // non-blocking mode.
                } else if err := syscall.SetNonblock(fdi, true); err == nil {
                        f.nonblock = true
                        clearNonBlock = true
@@ -247,7 +249,12 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
                syscall.CloseOnExec(r)
        }
 
-       return newFile(uintptr(r), name, kindOpenFile), nil
+       kind := kindOpenFile
+       if unix.HasNonblockFlag(flag) {
+               kind = kindNonBlock
+       }
+
+       return newFile(uintptr(r), name, kind), nil
 }
 
 func (file *file) close() error {