Skip to content

Commit f777726

Browse files
ianlancetaylorgopherbot
authored andcommitted
os: if descriptor is non-blocking, retain that in Fd method
For #58408 Fixes #60211 Change-Id: I30f5678b46e15121865b19d1c0f82698493fad4e Reviewed-on: https://go-review.googlesource.com/c/go/+/495079 Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Bryan Mills <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]>
1 parent f0de4b4 commit f777726

6 files changed

Lines changed: 78 additions & 5 deletions

File tree

src/internal/syscall/unix/nonblocking.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ func IsNonblock(fd int) (nonblocking bool, err error) {
1919
}
2020
return flag&syscall.O_NONBLOCK != 0, nil
2121
}
22+
23+
func HasNonblockFlag(flag int) bool {
24+
return flag&syscall.O_NONBLOCK != 0
25+
}

src/internal/syscall/unix/nonblocking_js.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ package unix
99
func IsNonblock(fd int) (nonblocking bool, err error) {
1010
return false, nil
1111
}
12+
13+
func HasNonblockFlag(flag int) bool {
14+
return false
15+
}

src/internal/syscall/unix/nonblocking_libc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ func IsNonblock(fd int) (nonblocking bool, err error) {
1919
return flag&syscall.O_NONBLOCK != 0, nil
2020
}
2121

22+
func HasNonblockFlag(flag int) bool {
23+
return flag&syscall.O_NONBLOCK != 0
24+
}
25+
2226
// Implemented in the syscall package.
2327
//
2428
//go:linkname fcntl syscall.fcntl

src/internal/syscall/unix/nonblocking_wasip1.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ func IsNonblock(fd int) (nonblocking bool, err error) {
1919
return flags&syscall.FDFLAG_NONBLOCK != 0, nil
2020
}
2121

22+
func HasNonblockFlag(flag int) bool {
23+
return flag&syscall.FDFLAG_NONBLOCK != 0
24+
}
25+
2226
// This helper is implemented in the syscall package. It means we don't have
2327
// to redefine the fd_fdstat_get host import or the fdstat struct it
2428
// populates.

src/os/fifo_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package os_test
88

99
import (
1010
"errors"
11+
"internal/syscall/unix"
1112
"internal/testenv"
1213
"io/fs"
1314
"os"
@@ -155,3 +156,52 @@ func TestNonPollable(t *testing.T) {
155156
}
156157
}
157158
}
159+
160+
// Issue 60211.
161+
func TestOpenFileNonBlocking(t *testing.T) {
162+
exe, err := os.Executable()
163+
if err != nil {
164+
t.Skipf("can't find executable: %v", err)
165+
}
166+
f, err := os.OpenFile(exe, os.O_RDONLY|syscall.O_NONBLOCK, 0666)
167+
if err != nil {
168+
t.Fatal(err)
169+
}
170+
defer f.Close()
171+
nonblock, err := unix.IsNonblock(int(f.Fd()))
172+
if err != nil {
173+
t.Fatal(err)
174+
}
175+
if !nonblock {
176+
t.Errorf("file opened with O_NONBLOCK but in blocking mode")
177+
}
178+
}
179+
180+
func TestNewFileNonBlocking(t *testing.T) {
181+
var p [2]int
182+
if err := syscall.Pipe(p[:]); err != nil {
183+
t.Fatal(err)
184+
}
185+
if err := syscall.SetNonblock(p[0], true); err != nil {
186+
t.Fatal(err)
187+
}
188+
f := os.NewFile(uintptr(p[0]), "pipe")
189+
nonblock, err := unix.IsNonblock(p[0])
190+
if err != nil {
191+
t.Fatal(err)
192+
}
193+
if !nonblock {
194+
t.Error("pipe blocking after NewFile")
195+
}
196+
fd := f.Fd()
197+
if fd != uintptr(p[0]) {
198+
t.Errorf("Fd returned %d, want %d", fd, p[0])
199+
}
200+
nonblock, err = unix.IsNonblock(p[0])
201+
if err != nil {
202+
t.Fatal(err)
203+
}
204+
if !nonblock {
205+
t.Error("pipe blocking after Fd")
206+
}
207+
}

src/os/file_unix.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,12 @@ const (
116116
// kindNewFile means that the descriptor was passed to us via NewFile.
117117
kindNewFile newFileKind = iota
118118
// kindOpenFile means that the descriptor was opened using
119-
// Open, Create, or OpenFile.
119+
// Open, Create, or OpenFile (without O_NONBLOCK).
120120
kindOpenFile
121121
// kindPipe means that the descriptor was opened using Pipe.
122122
kindPipe
123-
// kindNonBlock means that the descriptor was passed to us via NewFile,
124-
// and the descriptor is already in non-blocking mode.
123+
// kindNonBlock means that the descriptor is already in
124+
// non-blocking mode.
125125
kindNonBlock
126126
// kindNoPoll means that we should not put the descriptor into
127127
// non-blocking mode, because we know it is not a pipe or FIFO.
@@ -184,7 +184,9 @@ func newFile(fd uintptr, name string, kind newFileKind) *File {
184184
clearNonBlock := false
185185
if pollable {
186186
if kind == kindNonBlock {
187-
f.nonblock = true
187+
// The descriptor is already in non-blocking mode.
188+
// We only set f.nonblock if we put the file into
189+
// non-blocking mode.
188190
} else if err := syscall.SetNonblock(fdi, true); err == nil {
189191
f.nonblock = true
190192
clearNonBlock = true
@@ -263,7 +265,12 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
263265
syscall.CloseOnExec(r)
264266
}
265267

266-
f := newFile(uintptr(r), name, kindOpenFile)
268+
kind := kindOpenFile
269+
if unix.HasNonblockFlag(flag) {
270+
kind = kindNonBlock
271+
}
272+
273+
f := newFile(uintptr(r), name, kind)
267274
f.pfd.SysFile = s
268275
return f, nil
269276
}

0 commit comments

Comments
 (0)