diff options
| author | Will Hawkins <[email protected]> | 2023-04-15 19:14:13 -0400 |
|---|---|---|
| committer | Will Hawkins <[email protected]> | 2023-04-15 19:17:19 -0400 |
| commit | fd658c8e1ac37a770b62d5d5c53dfaaf9db256a6 (patch) | |
| tree | 557df76771cb44ca317f8997a0b2db51d9a68a09 | |
| parent | e59ddfd3672750351f80fb35c804827b2f726642 (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.go | 41 |
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 } |
