mirror of
https://github.com/golang/go
synced 2024-11-24 00:30:15 -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
|
l sync.Mutex
|
||||||
|
|
||||||
// For console I/O.
|
// For console I/O.
|
||||||
isConsole bool
|
|
||||||
lastbits []byte // first few bytes of the last incomplete rune in last write
|
lastbits []byte // first few bytes of the last incomplete rune in last write
|
||||||
readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole
|
readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole
|
||||||
readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8
|
readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8
|
||||||
@ -328,13 +327,23 @@ type FD struct {
|
|||||||
// message based socket connection.
|
// message based socket connection.
|
||||||
ZeroReadIsEOF bool
|
ZeroReadIsEOF bool
|
||||||
|
|
||||||
// Whether this is a normal file.
|
// Whether this is a file rather than a network socket.
|
||||||
isFile bool
|
isFile bool
|
||||||
|
|
||||||
// Whether this is a directory.
|
// The kind of this file.
|
||||||
isDir bool
|
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.
|
// logInitFD is set by tests to enable file descriptor initialization logging.
|
||||||
var logInitFD func(net string, fd *FD, err error)
|
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 {
|
switch net {
|
||||||
case "file":
|
case "file":
|
||||||
fd.isFile = true
|
fd.kind = kindFile
|
||||||
case "console":
|
case "console":
|
||||||
fd.isConsole = true
|
fd.kind = kindConsole
|
||||||
case "dir":
|
case "dir":
|
||||||
fd.isDir = true
|
fd.kind = kindDir
|
||||||
case "tcp", "tcp4", "tcp6":
|
case "tcp", "tcp4", "tcp6",
|
||||||
case "udp", "udp4", "udp6":
|
"udp", "udp4", "udp6",
|
||||||
case "ip", "ip4", "ip6":
|
"ip", "ip4", "ip6",
|
||||||
case "unix", "unixgram", "unixpacket":
|
"unix", "unixgram", "unixpacket":
|
||||||
|
fd.kind = kindNet
|
||||||
default:
|
default:
|
||||||
return "", errors.New("internal error: unknown network type " + net)
|
return "", errors.New("internal error: unknown network type " + net)
|
||||||
}
|
}
|
||||||
|
fd.isFile = fd.kind != kindNet
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if pollable {
|
if pollable {
|
||||||
@ -430,13 +441,14 @@ func (fd *FD) destroy() error {
|
|||||||
// so this must be executed before fd.CloseFunc.
|
// so this must be executed before fd.CloseFunc.
|
||||||
fd.pd.close()
|
fd.pd.close()
|
||||||
var err error
|
var err error
|
||||||
if fd.isFile || fd.isConsole {
|
switch fd.kind {
|
||||||
err = syscall.CloseHandle(fd.Sysfd)
|
case kindNet:
|
||||||
} else if fd.isDir {
|
|
||||||
err = syscall.FindClose(fd.Sysfd)
|
|
||||||
} else {
|
|
||||||
// The net package uses the CloseFunc variable for testing.
|
// The net package uses the CloseFunc variable for testing.
|
||||||
err = CloseFunc(fd.Sysfd)
|
err = CloseFunc(fd.Sysfd)
|
||||||
|
case kindDir:
|
||||||
|
err = syscall.FindClose(fd.Sysfd)
|
||||||
|
default:
|
||||||
|
err = syscall.CloseHandle(fd.Sysfd)
|
||||||
}
|
}
|
||||||
fd.Sysfd = syscall.InvalidHandle
|
fd.Sysfd = syscall.InvalidHandle
|
||||||
runtime_Semrelease(&fd.csema)
|
runtime_Semrelease(&fd.csema)
|
||||||
@ -485,12 +497,13 @@ func (fd *FD) Read(buf []byte) (int, error) {
|
|||||||
|
|
||||||
var n int
|
var n int
|
||||||
var err error
|
var err error
|
||||||
if fd.isFile || fd.isDir || fd.isConsole {
|
if fd.isFile {
|
||||||
fd.l.Lock()
|
fd.l.Lock()
|
||||||
defer fd.l.Unlock()
|
defer fd.l.Unlock()
|
||||||
if fd.isConsole {
|
switch fd.kind {
|
||||||
|
case kindConsole:
|
||||||
n, err = fd.readConsole(buf)
|
n, err = fd.readConsole(buf)
|
||||||
} else {
|
default:
|
||||||
n, err = syscall.Read(fd.Sysfd, buf)
|
n, err = syscall.Read(fd.Sysfd, buf)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -669,12 +682,13 @@ func (fd *FD) Write(buf []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
var n int
|
var n int
|
||||||
var err error
|
var err error
|
||||||
if fd.isFile || fd.isDir || fd.isConsole {
|
if fd.isFile {
|
||||||
fd.l.Lock()
|
fd.l.Lock()
|
||||||
defer fd.l.Unlock()
|
defer fd.l.Unlock()
|
||||||
if fd.isConsole {
|
switch fd.kind {
|
||||||
|
case kindConsole:
|
||||||
n, err = fd.writeConsole(b)
|
n, err = fd.writeConsole(b)
|
||||||
} else {
|
default:
|
||||||
n, err = syscall.Write(fd.Sysfd, b)
|
n, err = syscall.Write(fd.Sysfd, b)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2279,8 +2279,7 @@ func TestPipeThreads(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoubleCloseError(t *testing.T) {
|
func testDoubleCloseError(t *testing.T, path string) {
|
||||||
path := sfdir + "/" + sfname
|
|
||||||
file, err := Open(path)
|
file, err := Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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) {
|
func TestUserHomeDir(t *testing.T) {
|
||||||
dir, err := UserHomeDir()
|
dir, err := UserHomeDir()
|
||||||
if dir == "" && err == nil {
|
if dir == "" && err == nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user