From 2c630396f8cd8c5fa98b81dee06615e88e5f86f9 Mon Sep 17 00:00:00 2001 From: Steven Danna Date: Wed, 13 Mar 2024 21:03:07 +0000 Subject: [PATCH] fix checkptr in (*Mem).Get on darwin on Go 1.22 The unit tests currently fail under race on Go 1.22 on Darwin. > go test -race -v -run TestMem fatal error: checkptr: converted pointer straddles multiple allocations goroutine 35 gp=0xc000104c40 m=0 mp=0x104af4d00 [running]: runtime.throw({0x1048d66ee?, 0xc00012c7d8?}) /opt/homebrew/Cellar/go/1.22.1/libexec/src/runtime/panic.go:1023 +0x40 fp=0xc000067cc0 sp=0xc000067c90 pc=0x1046b8a20 runtime.checkptrAlignment(0x1048ca639?, 0xa?, 0x104af4d00?) /opt/homebrew/Cellar/go/1.22.1/libexec/src/runtime/checkptr.go:26 +0x70 fp=0xc000067ce0 sp=0xc000067cc0 pc=0x1046861e0 github.com/elastic/gosigar.sysctlbyname({0x1048ca639, 0xa}, {0x10494bca0, 0xc000067e30}) /Users/ssd/src/gosigar/sigar_common_darwin.go:483 +0xa8 fp=0xc000067d60 sp=0xc000067ce0 pc=0x1048800d8 github.com/elastic/gosigar.(*Mem).Get(0xc000067e30) /Users/ssd/src/gosigar/sigar_common_darwin.go:48 +0x78 fp=0xc000067df0 sp=0xc000067d60 pc=0x10487d2a8 github.com/elastic/gosigar_test.TestMem(0xc0001349c0) /Users/ssd/src/gosigar/sigar_interface_test.go:37 +0x3c fp=0xc000067ed0 sp=0xc000067df0 pc=0x10488242c testing.tRunner(0xc0001349c0, 0x104996310) /opt/homebrew/Cellar/go/1.22.1/libexec/src/testing/testing.go:1689 +0x184 fp=0xc000067fa0 sp=0xc000067ed0 pc=0x10478d1c4 testing.(*T).Run.gowrap1() /opt/homebrew/Cellar/go/1.22.1/libexec/src/testing/testing.go:1742 +0x44 fp=0xc000067fd0 sp=0xc000067fa0 pc=0x10478e664 runtime.goexit({}) /opt/homebrew/Cellar/go/1.22.1/libexec/src/runtime/asm_arm64.s:1222 +0x4 fp=0xc000067fd0 sp=0xc000067fd0 pc=0x1046f5894 created by testing.(*T).Run in goroutine 1 /opt/homebrew/Cellar/go/1.22.1/libexec/src/testing/testing.go:1742 +0x5e8 This is because syscall.Sysctl assumes that all return values are C strings and truncates the final byte if it is NUL. For Sysctl's that return integers, attempting to interpret the 7 byte buffer results in the checkptr violation. Here, we fix this by using the sys/unix packages SysctlUint64. --- sigar_common_darwin.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/sigar_common_darwin.go b/sigar_common_darwin.go index db02df71d..89e660a08 100644 --- a/sigar_common_darwin.go +++ b/sigar_common_darwin.go @@ -26,6 +26,8 @@ import ( "syscall" "time" "unsafe" + + "golang.org/x/sys/unix" ) // Get fetches LoadAverage data @@ -471,21 +473,23 @@ func vmInfo(vmstat *C.vm_statistics_data_t) error { // generic Sysctl buffer unmarshalling func sysctlbyname(name string, data interface{}) (err error) { - val, err := syscall.Sysctl(name) - if err != nil { - return err - } - - buf := []byte(val) - switch v := data.(type) { case *uint64: - *v = *(*uint64)(unsafe.Pointer(&buf[0])) - return - } + res, err := unix.SysctlUint64(name) + if err != nil { + return err + } + *v = res + return nil + default: + val, err := syscall.Sysctl(name) + if err != nil { + return err + } - bbuf := bytes.NewBuffer([]byte(val)) - return binary.Read(bbuf, binary.LittleEndian, data) + bbuf := bytes.NewBuffer([]byte(val)) + return binary.Read(bbuf, binary.LittleEndian, data) + } } func taskInfo(pid int, info *C.struct_proc_taskallinfo) error {