fix: use err from Syscall instead of calling GetLastError

Call() already returns the last error, see
https://pkg.go.dev/syscall?GOOS=windows#Proc.Call.

However, some code called GetLastError() afterwards, which is racy;
if the go routine switches threads between Call() and GetLastError(),
it may return a different error than expected, or possibly nil.
pull/1848/head
Max Altgelt 6 days ago
parent 15eaecda07
commit 7411b4e266
No known key found for this signature in database
GPG Key ID: D76CC9A61CFEB041

@ -71,12 +71,14 @@ func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
var lpIdleTime common.FILETIME
var lpKernelTime common.FILETIME
var lpUserTime common.FILETIME
r, _, _ := common.ProcGetSystemTimes.Call(
// GetSystemTimes returns 0 for error, in which case we check err,
// see https://pkg.go.dev/golang.org/x/sys/windows#LazyProc.Call
r, _, err := common.ProcGetSystemTimes.Call(
uintptr(unsafe.Pointer(&lpIdleTime)),
uintptr(unsafe.Pointer(&lpKernelTime)),
uintptr(unsafe.Pointer(&lpUserTime)))
if r == 0 {
return ret, windows.GetLastError()
return nil, err
}
LOT := float64(0.0000001)

@ -5,8 +5,6 @@ package mem
import (
"unsafe"
"golang.org/x/sys/windows"
)
// ExVirtualMemory represents Windows specific information
@ -28,16 +26,21 @@ func NewExWindows() *ExWindows {
func (e *ExWindows) VirtualMemory() (*ExVirtualMemory, error) {
var memInfo memoryStatusEx
memInfo.cbSize = uint32(unsafe.Sizeof(memInfo))
mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo)))
// If mem == 0 since this is an error according to GlobalMemoryStatusEx documentation
// In that case, use err which is constructed from GetLastError(),
// see https://pkg.go.dev/golang.org/x/sys/windows#LazyProc.Call
mem, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo)))
if mem == 0 {
return nil, windows.GetLastError()
return nil, err
}
var perfInfo performanceInformation
perfInfo.cb = uint32(unsafe.Sizeof(perfInfo))
perf, _, _ := procGetPerformanceInfo.Call(uintptr(unsafe.Pointer(&perfInfo)), uintptr(perfInfo.cb))
// Analogous to above: perf == 0 is an error according to the GetPerformanceInfo documentation,
// use err in that case
perf, _, err := procGetPerformanceInfo.Call(uintptr(unsafe.Pointer(&perfInfo)), uintptr(perfInfo.cb))
if perf == 0 {
return nil, windows.GetLastError()
return nil, err
}
ret := &ExVirtualMemory{

@ -40,9 +40,11 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
func VirtualMemoryWithContext(_ context.Context) (*VirtualMemoryStat, error) {
var memInfo memoryStatusEx
memInfo.cbSize = uint32(unsafe.Sizeof(memInfo))
mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo)))
// GlobalMemoryStatusEx returns 0 for error, in which case we check err,
// see https://pkg.go.dev/golang.org/x/sys/windows#LazyProc.Call
mem, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo)))
if mem == 0 {
return nil, windows.GetLastError()
return nil, err
}
ret := &VirtualMemoryStat{
@ -93,9 +95,11 @@ func SwapMemoryWithContext(_ context.Context) (*SwapMemoryStat, error) {
// Get total memory from performance information
var perfInfo performanceInformation
perfInfo.cb = uint32(unsafe.Sizeof(perfInfo))
mem, _, _ := procGetPerformanceInfo.Call(uintptr(unsafe.Pointer(&perfInfo)), uintptr(perfInfo.cb))
// GetPerformanceInfo returns 0 for error, in which case we check err,
// see https://pkg.go.dev/golang.org/x/sys/windows#LazyProc.Call
mem, _, err := procGetPerformanceInfo.Call(uintptr(unsafe.Pointer(&perfInfo)), uintptr(perfInfo.cb))
if mem == 0 {
return nil, windows.GetLastError()
return nil, err
}
totalPhys := perfInfo.physicalTotal * perfInfo.pageSize
totalSys := perfInfo.commitLimit * perfInfo.pageSize
@ -161,9 +165,11 @@ func SwapDevicesWithContext(_ context.Context) ([]*SwapDevice, error) {
// the following system call invokes the supplied callback function once for each page file before returning
// see https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumpagefilesw
var swapDevices []*SwapDevice
result, _, _ := procEnumPageFilesW.Call(windows.NewCallback(pEnumPageFileCallbackW), uintptr(unsafe.Pointer(&swapDevices)))
// EnumPageFilesW returns 0 for error, in which case we check err,
// see https://pkg.go.dev/golang.org/x/sys/windows#LazyProc.Call
result, _, err := procEnumPageFilesW.Call(windows.NewCallback(pEnumPageFileCallbackW), uintptr(unsafe.Pointer(&swapDevices)))
if result == 0 {
return nil, windows.GetLastError()
return nil, err
}
return swapDevices, nil

Loading…
Cancel
Save