Skip to content

Commit e28a0d3

Browse files
crvvianlancetaylor
authored andcommitted
os: don't wait for Close if the File was returned by NewFile
os.NewFile doesn't put the fd into non-blocking mode. In most cases, an *os.File returned by os.NewFile is in blocking mode. Updates #7970 Updates #21856 Updates #23111 Change-Id: Iab08432e41f7ac1b5e25aaa8855d478adb7f98ed Reviewed-on: https://go-review.googlesource.com/83995 Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent b944f91 commit e28a0d3

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

src/internal/poll/fd_unix.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ func (fd *FD) Init(net string, pollable bool) error {
5656
fd.isFile = true
5757
}
5858
if !pollable {
59+
fd.isBlocking = true
5960
return nil
6061
}
6162
return fd.pd.init(fd)

src/os/pipe_test.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package os_test
1010
import (
1111
"fmt"
1212
"internal/testenv"
13+
"io"
1314
"io/ioutil"
1415
"os"
1516
osexec "os/exec"
@@ -222,12 +223,28 @@ func TestReadNonblockingFd(t *testing.T) {
222223
}
223224
}
224225

225-
// Test that we don't let a blocking read prevent a close.
226-
func TestCloseWithBlockingRead(t *testing.T) {
226+
func TestCloseWithBlockingReadByNewFile(t *testing.T) {
227+
var p [2]int
228+
err := syscall.Pipe(p[:])
229+
if err != nil {
230+
t.Fatal(err)
231+
}
232+
// os.NewFile returns a blocking mode file.
233+
testCloseWithBlockingRead(t, os.NewFile(uintptr(p[0]), "reader"), os.NewFile(uintptr(p[1]), "writer"))
234+
}
235+
236+
func TestCloseWithBlockingReadByFd(t *testing.T) {
227237
r, w, err := os.Pipe()
228238
if err != nil {
229239
t.Fatal(err)
230240
}
241+
// Calling Fd will put the file into blocking mode.
242+
_ = r.Fd()
243+
testCloseWithBlockingRead(t, r, w)
244+
}
245+
246+
// Test that we don't let a blocking read prevent a close.
247+
func testCloseWithBlockingRead(t *testing.T, r, w *os.File) {
231248
defer r.Close()
232249
defer w.Close()
233250

@@ -248,18 +265,18 @@ func TestCloseWithBlockingRead(t *testing.T) {
248265
close(c)
249266
}(c1)
250267

251-
// Calling Fd will put the file into blocking mode.
252-
_ = r.Fd()
253-
254268
wg.Add(1)
255269
go func(c chan bool) {
256270
defer wg.Done()
257271
var b [1]byte
258-
_, err = r.Read(b[:])
272+
_, err := r.Read(b[:])
259273
close(c)
260274
if err == nil {
261275
t.Error("I/O on closed pipe unexpectedly succeeded")
262276
}
277+
if err != io.EOF {
278+
t.Errorf("got %v, expected io.EOF", err)
279+
}
263280
}(c2)
264281

265282
for c1 != nil || c2 != nil {

0 commit comments

Comments
 (0)