// Writev cache.
iovecs *[]syscall.Iovec
+ // Semaphore signaled when file is closed.
+ csema uint32
+
// Whether this is a streaming descriptor, as opposed to a
// packet-based descriptor like a UDP socket. Immutable.
IsStream bool
fd.pd.close()
err := CloseFunc(fd.Sysfd)
fd.Sysfd = -1
+ runtime_Semrelease(&fd.csema)
return err
}
fd.pd.evict()
// The call to decref will call destroy if there are no other
// references.
- return fd.decref()
+ err := fd.decref()
+ // Wait until the descriptor is closed. If this was the only
+ // reference, it is already closed.
+ runtime_Semacquire(&fd.csema)
+ return err
}
// Shutdown wraps the shutdown network call.
readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8
readbyteOffset int // readbyte[readOffset:] is yet to be consumed with file.Read
+ // Semaphore signaled when file is closed.
+ csema uint32
+
skipSyncNotif bool
// Whether this is a streaming descriptor, as opposed to a
err = CloseFunc(fd.Sysfd)
}
fd.Sysfd = syscall.InvalidHandle
+ runtime_Semrelease(&fd.csema)
return err
}
}
// unblock pending reader and writer
fd.pd.evict()
- return fd.decref()
+ err := fd.decref()
+ // Wait until the descriptor is closed. If this was the only
+ // reference, it is already closed.
+ runtime_Semacquire(&fd.csema)
+ return err
}
// Shutdown wraps the shutdown network call.
"runtime"
"syscall"
"testing"
+ "time"
)
func (ln *TCPListener) port() string {
}
return false, nil
}
+
+// Issue 21856.
+func TestClosingListener(t *testing.T) {
+ listener, err := Listen("tcp", ":0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ addr := listener.Addr()
+
+ go func() {
+ for {
+ c, err := listener.Accept()
+ if err != nil {
+ return
+ }
+ c.Close()
+ }
+ }()
+
+ // Let the goroutine start. We don't sleep long: if the
+ // goroutine doesn't start, the test will pass without really
+ // testing anything, which is OK.
+ time.Sleep(time.Millisecond)
+
+ listener.Close()
+
+ _, err = Listen("tcp", addr.String())
+ if err != nil {
+ t.Error(err)
+ }
+}