From a949bb5d7d160c412c3a5f9d48b54b9377611e1e Mon Sep 17 00:00:00 2001 From: Hamza El-Saawy Date: Mon, 7 Feb 2022 18:25:37 -0500 Subject: [PATCH] `HvsockConn` shutdown, and `.IsClosed()` function Corrected `HvsockConn` `CloseRead`/`Write` to check if the socket has been closed before attempting to shutdown reading or writing. Additionally, `shutdown` was not respecting whether to shutdown reading or writing, and only shutting down reading. Added a `CloseReadWrite` function to `HvsockConn` to expose shutting down both ends of the connection. Added `IsClosed` function to `win32File` (and therefore `win32Pipe` and `win32MessageBytePipe`) and `HvsockConn` to check if the socket/pipe has been closed already. Signed-off-by: Hamza El-Saawy --- file.go | 6 ++++++ hvsock.go | 22 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/file.go b/file.go index 0385e410..293ab54c 100644 --- a/file.go +++ b/file.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -143,6 +144,11 @@ func (f *win32File) Close() error { return nil } +// IsClosed checks if the file has been closed +func (f *win32File) IsClosed() bool { + return f.closing.isSet() +} + // prepareIo prepares for a new IO operation. // The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. func (f *win32File) prepareIo() (*ioOperation, error) { diff --git a/hvsock.go b/hvsock.go index b632f8f8..fa627e61 100644 --- a/hvsock.go +++ b/hvsock.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -252,15 +253,23 @@ func (conn *HvsockConn) Close() error { return conn.sock.Close() } +func (conn *HvsockConn) IsClosed() bool { + return conn.sock.IsClosed() +} + func (conn *HvsockConn) shutdown(how int) error { - err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) + if conn.IsClosed() { + return ErrFileClosed + } + + err := syscall.Shutdown(conn.sock.handle, how) if err != nil { return os.NewSyscallError("shutdown", err) } return nil } -// CloseRead shuts down the read end of the socket. +// CloseRead shuts down the read end of the socket, preventing future read operations. func (conn *HvsockConn) CloseRead() error { err := conn.shutdown(syscall.SHUT_RD) if err != nil { @@ -279,6 +288,15 @@ func (conn *HvsockConn) CloseWrite() error { return nil } +// CloseReadWrite shuts down both the read and write end of the socket, preventing future operations. +func (conn *HvsockConn) CloseReadWrite() error { + err := conn.shutdown(syscall.SHUT_RDWR) + if err != nil { + return conn.opErr("close", err) + } + return nil +} + // LocalAddr returns the local address of the connection. func (conn *HvsockConn) LocalAddr() net.Addr { return &conn.local