mirror of
https://github.com/golang/go
synced 2024-11-19 11:24:51 -07:00
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 <iant@golang.org>
This commit is contained in:
parent
b944f91f15
commit
e28a0d397b
@ -56,6 +56,7 @@ func (fd *FD) Init(net string, pollable bool) error {
|
|||||||
fd.isFile = true
|
fd.isFile = true
|
||||||
}
|
}
|
||||||
if !pollable {
|
if !pollable {
|
||||||
|
fd.isBlocking = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fd.pd.init(fd)
|
return fd.pd.init(fd)
|
||||||
|
@ -10,6 +10,7 @@ package os_test
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
osexec "os/exec"
|
osexec "os/exec"
|
||||||
@ -222,12 +223,28 @@ func TestReadNonblockingFd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that we don't let a blocking read prevent a close.
|
func TestCloseWithBlockingReadByNewFile(t *testing.T) {
|
||||||
func TestCloseWithBlockingRead(t *testing.T) {
|
var p [2]int
|
||||||
|
err := syscall.Pipe(p[:])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// os.NewFile returns a blocking mode file.
|
||||||
|
testCloseWithBlockingRead(t, os.NewFile(uintptr(p[0]), "reader"), os.NewFile(uintptr(p[1]), "writer"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCloseWithBlockingReadByFd(t *testing.T) {
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
// Calling Fd will put the file into blocking mode.
|
||||||
|
_ = r.Fd()
|
||||||
|
testCloseWithBlockingRead(t, r, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that we don't let a blocking read prevent a close.
|
||||||
|
func testCloseWithBlockingRead(t *testing.T, r, w *os.File) {
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
defer w.Close()
|
defer w.Close()
|
||||||
|
|
||||||
@ -248,18 +265,18 @@ func TestCloseWithBlockingRead(t *testing.T) {
|
|||||||
close(c)
|
close(c)
|
||||||
}(c1)
|
}(c1)
|
||||||
|
|
||||||
// Calling Fd will put the file into blocking mode.
|
|
||||||
_ = r.Fd()
|
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(c chan bool) {
|
go func(c chan bool) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
var b [1]byte
|
var b [1]byte
|
||||||
_, err = r.Read(b[:])
|
_, err := r.Read(b[:])
|
||||||
close(c)
|
close(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("I/O on closed pipe unexpectedly succeeded")
|
t.Error("I/O on closed pipe unexpectedly succeeded")
|
||||||
}
|
}
|
||||||
|
if err != io.EOF {
|
||||||
|
t.Errorf("got %v, expected io.EOF", err)
|
||||||
|
}
|
||||||
}(c2)
|
}(c2)
|
||||||
|
|
||||||
for c1 != nil || c2 != nil {
|
for c1 != nil || c2 != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user