Skip to content

Commit 34d28ba

Browse files
committed
internal/syscall/windows: implement SupportUnixSocket by enumerating protocols
windows.SupportUnixSocket is currently implemented using a Windows version check. This approach is not reliable, see #27943 and #28061. Also, it uses the undocumented RtlGetNtVersionNumbers API, which we should try to avoid. This PR implements SupportUnixSocket by enumerating the available protocols and checking for AF_UNIX support. Cq-Include-Trybots: luci.golang.try:gotip-windows-arm64 Change-Id: I76cd635067309f09571ad0eac4a5699450a2709a Reviewed-on: https://go-review.googlesource.com/c/go/+/570075 Reviewed-by: Cherry Mui <[email protected]> Reviewed-by: Alex Brainman <[email protected]> Reviewed-by: Bryan Mills <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 293fadf commit 34d28ba

File tree

4 files changed

+58
-19
lines changed

4 files changed

+58
-19
lines changed

src/internal/syscall/windows/syscall_windows.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ const (
201201
WSA_FLAG_OVERLAPPED = 0x01
202202
WSA_FLAG_NO_HANDLE_INHERIT = 0x80
203203

204-
WSAEMSGSIZE syscall.Errno = 10040
204+
WSAEINVAL syscall.Errno = 10022
205+
WSAEMSGSIZE syscall.Errno = 10040
206+
WSAEAFNOSUPPORT syscall.Errno = 10047
205207

206208
MSG_PEEK = 0x2
207209
MSG_TRUNC = 0x0100

src/internal/syscall/windows/version_windows.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ package windows
66

77
import (
88
"sync"
9-
_ "unsafe" // for linkname
9+
"syscall"
10+
"unsafe"
1011
)
1112

1213
// version retrieves the major, minor, and build version numbers
@@ -42,6 +43,21 @@ var SupportTCPInitialRTONoSYNRetransmissions = sync.OnceValue(func() bool {
4243
// Unix Domain Sockets.
4344
// The minimal requirement is Windows 10.0.17063.
4445
var SupportUnixSocket = sync.OnceValue(func() bool {
45-
major, _, build := version()
46-
return major >= 10 && build >= 17063
46+
var size uint32
47+
// First call to get the required buffer size in bytes.
48+
// Ignore the error, it will always fail.
49+
_, _ = syscall.WSAEnumProtocols(nil, nil, &size)
50+
n := int32(size) / int32(unsafe.Sizeof(syscall.WSAProtocolInfo{}))
51+
// Second call to get the actual protocols.
52+
buf := make([]syscall.WSAProtocolInfo, n)
53+
n, err := syscall.WSAEnumProtocols(nil, &buf[0], &size)
54+
if err != nil {
55+
return false
56+
}
57+
for i := int32(0); i < n; i++ {
58+
if buf[i].AddressFamily == syscall.AF_UNIX {
59+
return true
60+
}
61+
}
62+
return false
4763
})
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package windows_test
6+
7+
import (
8+
"errors"
9+
"internal/syscall/windows"
10+
"syscall"
11+
"testing"
12+
)
13+
14+
func TestSupportUnixSocket(t *testing.T) {
15+
var d syscall.WSAData
16+
if err := syscall.WSAStartup(uint32(0x202), &d); err != nil {
17+
t.Fatal(err)
18+
}
19+
defer syscall.WSACleanup()
20+
21+
// Test that SupportUnixSocket returns true if WSASocket succeeds with AF_UNIX.
22+
got := windows.SupportUnixSocket()
23+
s, err := windows.WSASocket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0, nil, 0, windows.WSA_FLAG_NO_HANDLE_INHERIT)
24+
if err == nil {
25+
syscall.Closesocket(s)
26+
}
27+
want := !errors.Is(err, windows.WSAEAFNOSUPPORT) && !errors.Is(err, windows.WSAEINVAL)
28+
if want != got {
29+
t.Errorf("SupportUnixSocket = %v; want %v", got, want)
30+
}
31+
}

src/net/unixsock_windows_test.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,13 @@ import (
1010
"internal/syscall/windows"
1111
"os"
1212
"reflect"
13-
"runtime"
1413
"testing"
1514
)
1615

17-
func skipIfUnixSocketNotSupported(t *testing.T) {
18-
// TODO: the windows.SupportUnixSocket check should be enough, investigate why 386 and arm
19-
// can't run these tests on newer Windows.
20-
switch runtime.GOARCH {
21-
case "386":
22-
t.Skip("not supported on windows/386, see golang.org/issue/27943")
23-
case "arm":
24-
t.Skip("not supported on windows/arm, see golang.org/issue/28061")
25-
}
16+
func TestUnixConnLocalWindows(t *testing.T) {
2617
if !windows.SupportUnixSocket() {
2718
t.Skip("unix test")
2819
}
29-
}
30-
31-
func TestUnixConnLocalWindows(t *testing.T) {
32-
skipIfUnixSocketNotSupported(t)
3320
handler := func(ls *localServer, ln Listener) {}
3421
for _, laddr := range []string{"", testUnixAddr(t)} {
3522
laddr := laddr
@@ -83,7 +70,10 @@ func TestUnixConnLocalWindows(t *testing.T) {
8370
}
8471

8572
func TestModeSocket(t *testing.T) {
86-
skipIfUnixSocketNotSupported(t)
73+
if !windows.SupportUnixSocket() {
74+
t.Skip("unix test")
75+
}
76+
8777
addr := testUnixAddr(t)
8878

8979
l, err := Listen("unix", addr)

0 commit comments

Comments
 (0)