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
"bufio"
"bytes"
"fmt"
+ "internal/syscall/unix"
"io"
"os"
"path/filepath"
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")
+ }
+}
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
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 {