From 9368ced7555d9320e93e83e18a67faa9af1226b9 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Fri, 19 Jan 2024 16:27:22 +0100 Subject: [PATCH] net,internal/poll: load ws2_32.dll only when net is imported On Windows, ws2_32.dll is loaded and WSA initialized even if websockets are not used. This CL delays loading of ws2_32.dll and starting WSA until net is initialized. Change-Id: I07ea8241d79709cd4e80d29ba0d792c7444bbfe9 Reviewed-on: https://go-review.googlesource.com/c/go/+/557015 Reviewed-by: Bryan Mills Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/cmd/go/testdata/script/ws2_32.txt | 48 +++++++++++++++++++++++++++ src/internal/poll/fd_windows.go | 7 ++-- src/internal/poll/fd_windows_test.go | 2 ++ src/net/fd_windows.go | 4 +++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/cmd/go/testdata/script/ws2_32.txt diff --git a/src/cmd/go/testdata/script/ws2_32.txt b/src/cmd/go/testdata/script/ws2_32.txt new file mode 100644 index 0000000000..54f6a94eaf --- /dev/null +++ b/src/cmd/go/testdata/script/ws2_32.txt @@ -0,0 +1,48 @@ +[!GOOS:windows] skip + +go run . +stdout 'ws2_32.dll: not found' + +go run -tags net . +stdout 'ws2_32.dll: found' + +-- go.mod -- +module m + +go 1.21 + +-- utils.go -- +package main + +import ( + "fmt" + "syscall" + "unsafe" +) + +func hasModuleHandle() { + const ws2_32 = "ws2_32.dll" + getModuleHandle := syscall.MustLoadDLL("kernel32.dll").MustFindProc("GetModuleHandleW") + mod, _, _ := getModuleHandle.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(ws2_32)))) + if mod != 0 { + fmt.Println(ws2_32+":", "found") + } else { + fmt.Println(ws2_32+":", "not found") + } +} +-- net.go -- +//go:build net +package main + +import _ "net" + +func main() { + hasModuleHandle() +} +-- nonet.go -- +//go:build !net +package main + +func main() { + hasModuleHandle() +} \ No newline at end of file diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index fe23d4b3d7..b08ca615c6 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -53,14 +53,17 @@ func checkSetFileCompletionNotificationModes() { useSetFileCompletionNotificationModes = true } -func init() { +// InitWSA initiates the use of the Winsock DLL by the current process. +// It is called from the net package at init time to avoid +// loading ws2_32.dll when net is not used. +var InitWSA = sync.OnceFunc(func() { var d syscall.WSAData e := syscall.WSAStartup(uint32(0x202), &d) if e != nil { initErr = e } checkSetFileCompletionNotificationModes() -} +}) // operation contains superset of data necessary to perform all async IO. type operation struct { diff --git a/src/internal/poll/fd_windows_test.go b/src/internal/poll/fd_windows_test.go index f0697a0d7b..1cee18dcba 100644 --- a/src/internal/poll/fd_windows_test.go +++ b/src/internal/poll/fd_windows_test.go @@ -41,6 +41,8 @@ func logFD(net string, fd *poll.FD, err error) { func init() { loggedFDs = make(map[syscall.Handle]*loggedFD) *poll.LogInitFD = logFD + + poll.InitWSA() } func findLoggedFD(h syscall.Handle) (lfd *loggedFD, found bool) { diff --git a/src/net/fd_windows.go b/src/net/fd_windows.go index 45a10cf1eb..f9a077b631 100644 --- a/src/net/fd_windows.go +++ b/src/net/fd_windows.go @@ -23,6 +23,10 @@ const ( writeMsgSyscallName = "wsasendmsg" ) +func init() { + poll.InitWSA() +} + // canUseConnectEx reports whether we can use the ConnectEx Windows API call // for the given network type. func canUseConnectEx(net string) bool {