Skip to content

Hyper-v socket close implementation uses CloseHandle instead of closesocket #330

@Snshadow

Description

@Snshadow

While looking into Hyper-V socket implementation for using it within a service from vm, I have found out that implementation from HvSocketConn and HvSocketListener uses windows.Close to close a created socket, which calls windows.CloseHandle internally.

go-winio/hvsock.go

Lines 166 to 170 in bdc6c11

// HvsockListener is a socket listener for the AF_HYPERV address family.
type HvsockListener struct {
sock *win32File
addr HvsockAddr
}

go-winio/hvsock.go

Lines 284 to 286 in bdc6c11

func (l *HvsockListener) Close() error {
return l.sock.Close()
}

go-winio/hvsock.go

Lines 174 to 178 in bdc6c11

// HvsockConn is a connected socket of the AF_HYPERV address family.
type HvsockConn struct {
sock *win32File
local, remote HvsockAddr
}

go-winio/hvsock.go

Lines 507 to 509 in bdc6c11

func (conn *HvsockConn) Close() error {
return conn.sock.Close()
}

go-winio/file.go

Lines 113 to 134 in bdc6c11

// closeHandle closes the resources associated with a Win32 handle.
func (f *win32File) closeHandle() {
f.wgLock.Lock()
// Atomically set that we are closing, releasing the resources only once.
if !f.closing.Swap(true) {
f.wgLock.Unlock()
// cancel all IO and wait for it to complete
_ = cancelIoEx(f.handle, nil)
f.wg.Wait()
// at this point, no new IO can start
windows.Close(f.handle)
f.handle = 0
} else {
f.wgLock.Unlock()
}
}
// Close closes a win32File.
func (f *win32File) Close() error {
f.closeHandle()
return nil
}

from "golang.org/x/sys/windows..

func Close(fd Handle) (err error) {
	return CloseHandle(fd)
}

However it is stated that in CloseHandle

Do not use the CloseHandle function to close a socket. Instead, use the closesocket function, which releases all resources associated with the socket including the handle to the socket object. For more information, see Socket Closure.

which makes this look like doing something like

// closeHandle closes the resources associated with a Win32 handle.
func (f *win32File) closeHandle() {
	f.wgLock.Lock()
	// Atomically set that we are closing, releasing the resources only once.
	if !f.closing.Swap(true) {
		f.wgLock.Unlock()
		// cancel all IO and wait for it to complete
		_ = cancelIoEx(f.handle, nil)
		f.wg.Wait()
		// at this point, no new IO can start
		if f.socket {
			windows.Closesocket(f.handle)
		} else {
			windows.Close(f.handle)
		}
		f.handle = 0
	} else {
		f.wgLock.Unlock()
	}
}

would be required to close a socket instead of a regular windows file?

Is using windows.CloseHandle a valid approach for closing a Hyper-V socket as it is not a common network socket or is this something needs to be fixed?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions