summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Hawkins <[email protected]>2023-04-15 19:14:13 -0400
committerWill Hawkins <[email protected]>2023-04-15 19:17:19 -0400
commitfd658c8e1ac37a770b62d5d5c53dfaaf9db256a6 (patch)
tree557df76771cb44ca317f8997a0b2db51d9a68a09
parente59ddfd3672750351f80fb35c804827b2f726642 (diff)
[Bugfix] Call windows.WSAIoctl safely when getting extended stats in windows.go
Based on CL482495 in the go runtime, there is now a proper way to safely do overlapped IO on Windows. This patch adopts those precautions.
-rw-r--r--extendedstats/windows.go41
1 files changed, 41 insertions, 0 deletions
diff --git a/extendedstats/windows.go b/extendedstats/windows.go
index 063d29a..f7ce580 100644
--- a/extendedstats/windows.go
+++ b/extendedstats/windows.go
@@ -19,6 +19,7 @@ package extendedstats
import (
"crypto/tls"
+ "errors"
"fmt"
"net"
"unsafe"
@@ -186,6 +187,14 @@ func getTCPInfoRaw(basicConn net.Conn) (*TCPINFO_V1, error) {
overlapped := windows.Overlapped{}
+ eventHandle, err := windows.CreateEvent(nil, 0, 0, nil)
+
+ if err != nil {
+ return nil, fmt.Errorf("OOPS: CreateEvent failed during extended stats capture: %v", err)
+ }
+ overlapped.HEvent = eventHandle
+ overlapped.HEvent = (windows.Handle)((uintptr)(eventHandle)) | 0x1
+
completionRoutine := uintptr(0)
rawConn.Control(func(fd uintptr) {
@@ -201,6 +210,38 @@ func getTCPInfoRaw(basicConn net.Conn) (*TCPINFO_V1, error) {
completionRoutine,
)
})
+
+ if err != nil {
+ /* An error might just indicate that the result is not immediately available.
+ * If that is the case, we will wait until it is.
+ */
+ if errors.Is(err, windows.ERROR_IO_PENDING /*AKA, WSA_IO_PENDING*/) {
+ _, err = windows.WaitForSingleObject(overlapped.HEvent, windows.INFINITE)
+ if err != nil {
+ return nil, fmt.Errorf("OOPS: WaitForSingleObject failed during extended stats capture: %v", err)
+ }
+ rawConn.Control(func(fd uintptr) {
+ err = windows.GetOverlappedResult(
+ windows.Handle(fd),
+ &overlapped,
+ &cbbr,
+ false,
+ )
+ })
+ if err != nil {
+ return nil, fmt.Errorf("OOPS: GetOverlappedResult failed during extended stats capture: %v", err)
+ }
+ } else {
+ return nil, fmt.Errorf("OOPS: WSAIoctl failed: %v", err)
+ }
+ }
+
+ windows.CloseHandle(overlapped.HEvent)
+
+ if cbbr != cbob {
+ return nil, fmt.Errorf("WSAIoctl did not get valid information about the TCP connection")
+ }
+
return &outbuf, err
}