mirror of
https://github.com/golang/go
synced 2024-11-23 20:00:04 -07:00
internal/poll: make FD.isFile mean whether it isn't socket on Windows
Before this change, if a directory was closed twice on Windows,
the returning error would be "use of closed network connection".
Some code assumes FD.isFile means whether the fd isn't a network
socket, which is true on Unix. But isFile reports whether
the fd is a normal file rather than directory or console on Windows.
With this change, isFile will have the same meaning on different
platforms. And the change adds a new field kind to replace isConsole
and isDir.
Change-Id: Ib12265f1e12fa3d0239ae925291128a84be59cc2
GitHub-Last-Rev: 3f031756de
GitHub-Pull-Request: golang/go#30589
Reviewed-on: https://go-review.googlesource.com/c/go/+/165257
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
029a5af6a1
commit
a60b56adbe
@ -309,7 +309,6 @@ type FD struct {
|
||||
l sync.Mutex
|
||||
|
||||
// For console I/O.
|
||||
isConsole bool
|
||||
lastbits []byte // first few bytes of the last incomplete rune in last write
|
||||
readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole
|
||||
readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8
|
||||
@ -328,13 +327,23 @@ type FD struct {
|
||||
// message based socket connection.
|
||||
ZeroReadIsEOF bool
|
||||
|
||||
// Whether this is a normal file.
|
||||
// Whether this is a file rather than a network socket.
|
||||
isFile bool
|
||||
|
||||
// Whether this is a directory.
|
||||
isDir bool
|
||||
// The kind of this file.
|
||||
kind fileKind
|
||||
}
|
||||
|
||||
// fileKind describes the kind of file.
|
||||
type fileKind byte
|
||||
|
||||
const (
|
||||
kindNet fileKind = iota
|
||||
kindFile
|
||||
kindConsole
|
||||
kindDir
|
||||
)
|
||||
|
||||
// logInitFD is set by tests to enable file descriptor initialization logging.
|
||||
var logInitFD func(net string, fd *FD, err error)
|
||||
|
||||
@ -350,18 +359,20 @@ func (fd *FD) Init(net string, pollable bool) (string, error) {
|
||||
|
||||
switch net {
|
||||
case "file":
|
||||
fd.isFile = true
|
||||
fd.kind = kindFile
|
||||
case "console":
|
||||
fd.isConsole = true
|
||||
fd.kind = kindConsole
|
||||
case "dir":
|
||||
fd.isDir = true
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
case "udp", "udp4", "udp6":
|
||||
case "ip", "ip4", "ip6":
|
||||
case "unix", "unixgram", "unixpacket":
|
||||
fd.kind = kindDir
|
||||
case "tcp", "tcp4", "tcp6",
|
||||
"udp", "udp4", "udp6",
|
||||
"ip", "ip4", "ip6",
|
||||
"unix", "unixgram", "unixpacket":
|
||||
fd.kind = kindNet
|
||||
default:
|
||||
return "", errors.New("internal error: unknown network type " + net)
|
||||
}
|
||||
fd.isFile = fd.kind != kindNet
|
||||
|
||||
var err error
|
||||
if pollable {
|
||||
@ -430,13 +441,14 @@ func (fd *FD) destroy() error {
|
||||
// so this must be executed before fd.CloseFunc.
|
||||
fd.pd.close()
|
||||
var err error
|
||||
if fd.isFile || fd.isConsole {
|
||||
err = syscall.CloseHandle(fd.Sysfd)
|
||||
} else if fd.isDir {
|
||||
err = syscall.FindClose(fd.Sysfd)
|
||||
} else {
|
||||
switch fd.kind {
|
||||
case kindNet:
|
||||
// The net package uses the CloseFunc variable for testing.
|
||||
err = CloseFunc(fd.Sysfd)
|
||||
case kindDir:
|
||||
err = syscall.FindClose(fd.Sysfd)
|
||||
default:
|
||||
err = syscall.CloseHandle(fd.Sysfd)
|
||||
}
|
||||
fd.Sysfd = syscall.InvalidHandle
|
||||
runtime_Semrelease(&fd.csema)
|
||||
@ -485,12 +497,13 @@ func (fd *FD) Read(buf []byte) (int, error) {
|
||||
|
||||
var n int
|
||||
var err error
|
||||
if fd.isFile || fd.isDir || fd.isConsole {
|
||||
if fd.isFile {
|
||||
fd.l.Lock()
|
||||
defer fd.l.Unlock()
|
||||
if fd.isConsole {
|
||||
switch fd.kind {
|
||||
case kindConsole:
|
||||
n, err = fd.readConsole(buf)
|
||||
} else {
|
||||
default:
|
||||
n, err = syscall.Read(fd.Sysfd, buf)
|
||||
}
|
||||
if err != nil {
|
||||
@ -669,12 +682,13 @@ func (fd *FD) Write(buf []byte) (int, error) {
|
||||
}
|
||||
var n int
|
||||
var err error
|
||||
if fd.isFile || fd.isDir || fd.isConsole {
|
||||
if fd.isFile {
|
||||
fd.l.Lock()
|
||||
defer fd.l.Unlock()
|
||||
if fd.isConsole {
|
||||
switch fd.kind {
|
||||
case kindConsole:
|
||||
n, err = fd.writeConsole(b)
|
||||
} else {
|
||||
default:
|
||||
n, err = syscall.Write(fd.Sysfd, b)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -2279,8 +2279,7 @@ func TestPipeThreads(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoubleCloseError(t *testing.T) {
|
||||
path := sfdir + "/" + sfname
|
||||
func testDoubleCloseError(t *testing.T, path string) {
|
||||
file, err := Open(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -2299,6 +2298,11 @@ func TestDoubleCloseError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoubleCloseError(t *testing.T) {
|
||||
testDoubleCloseError(t, filepath.Join(sfdir, sfname))
|
||||
testDoubleCloseError(t, sfdir)
|
||||
}
|
||||
|
||||
func TestUserHomeDir(t *testing.T) {
|
||||
dir, err := UserHomeDir()
|
||||
if dir == "" && err == nil {
|
||||
|
Loading…
Reference in New Issue
Block a user