]> Cypherpunks repositories - gostls13.git/commitdiff
internal/poll: make FD.isFile mean whether it isn't socket on Windows
authorWèi Cōngruì <crvv.mail@gmail.com>
Wed, 6 Mar 2019 08:43:27 +0000 (08:43 +0000)
committerIan Lance Taylor <iant@golang.org>
Wed, 6 Mar 2019 18:04:33 +0000 (18:04 +0000)
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: 3f031756de6ce0b96c1f102ad280950f4adbf6c2
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>
src/internal/poll/fd_windows.go
src/os/os_test.go

index 19d9a12dad83b9b9e1d388c113328fc0dc409bea..eeef5a78d3a2cc3b8229425ad1298ba15ac8536c 100644 (file)
@@ -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 {
index 9c4d5dada9a106b9c20c593bd157a88b804e6371..c5c6b49e8f427e5a2b339f4b3fd0d553e548e3b1 100644 (file)
@@ -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 {