From 19082b35aed83fc1d7de0f6acac35a98684b25c6 Mon Sep 17 00:00:00 2001 From: Li Chuangbo Date: Mon, 30 Dec 2024 15:29:23 +0800 Subject: [PATCH] fix: memory leak and string corruption in ARM Mac temperature sensors This commit addresses several issues in the temperature sensor implementation for ARM Mac: 1. Memory leak caused by unreleased system resources 2. Increasing port counts in Activity Monitor 3. String corruption where the first character becomes "\x00" Changes: 1. Resource Management: - Added proper resource cleanup using `defer` statements - Refactored code to share the HID system client instead of creating new ones - Fixed memory leaks by ensuring all CoreFoundation objects are properly released 2. String Handling: - Fixed buffer allocation for string conversion - Properly handle null terminators in C string to Go string conversion - Added correct string length calculations 3. Code Structure: - Reduced resource allocation by sharing system client between functions - Enhanced code readability with better comments --- sensors/sensors_darwin_arm64.go | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sensors/sensors_darwin_arm64.go b/sensors/sensors_darwin_arm64.go index 509faddcf..8a7b91aa2 100644 --- a/sensors/sensors_darwin_arm64.go +++ b/sensors/sensors_darwin_arm64.go @@ -41,11 +41,16 @@ func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { } ta.matching(0xff00, 5) - thermalNames := ta.getProductNames() - thermalValues := ta.getThermalValues() + defer ta.cfRelease(uintptr(ta.sensors)) + + // Create HID system client + system := ta.ioHIDEventSystemClientCreate(common.KCFAllocatorDefault) + defer ta.cfRelease(uintptr(system)) + + thermalNames := ta.getProductNames(system) + thermalValues := ta.getThermalValues(system) result := dumpNameValues(thermalNames, thermalValues) - ta.cfRelease(uintptr(ta.sensors)) return result, nil } @@ -84,14 +89,12 @@ type temperatureArm struct { sensors unsafe.Pointer } -func (ta *temperatureArm) getProductNames() []string { +func (ta *temperatureArm) getProductNames(system unsafe.Pointer) []string { ioHIDServiceClientCopyProperty := common.GetFunc[common.IOHIDServiceClientCopyPropertyFunc](ta.ioKit, common.IOHIDServiceClientCopyPropertySym) - cfStringGetLength := common.GetFunc[common.CFStringGetLengthFunc](ta.cf, common.CFStringGetLengthSym) cfStringGetCString := common.GetFunc[common.CFStringGetCStringFunc](ta.cf, common.CFStringGetCStringSym) var names []string - system := ta.ioHIDEventSystemClientCreate(common.KCFAllocatorDefault) ta.ioHIDEventSystemClientSetMatching(uintptr(system), uintptr(ta.sensors)) matchingsrvs := ta.ioHIDEventSystemClientCopyServices(uintptr(system)) @@ -99,44 +102,44 @@ func (ta *temperatureArm) getProductNames() []string { if matchingsrvs == nil { return nil } + defer ta.cfRelease(uintptr(matchingsrvs)) count := ta.cfArrayGetCount(uintptr(matchingsrvs)) var i int32 str := ta.cfStr("Product") + defer ta.cfRelease(uintptr(str)) + for i = 0; i < count; i++ { sc := ta.cfArrayGetValueAtIndex(uintptr(matchingsrvs), i) name := ioHIDServiceClientCopyProperty(uintptr(sc), uintptr(str)) if name != nil { - length := cfStringGetLength(uintptr(name)) + 1 // null terminator - buf := make([]byte, length-1) + length := cfStringGetLength(uintptr(name)) + 1 // include null terminator + buf := make([]byte, length) // allocate buffer with full length cfStringGetCString(uintptr(name), &buf[0], length, common.KCFStringEncodingUTF8) - names = append(names, string(buf)) + names = append(names, string(buf[:length-1])) // remove null terminator ta.cfRelease(uintptr(name)) } else { names = append(names, "noname") } } - ta.cfRelease(uintptr(matchingsrvs)) - ta.cfRelease(uintptr(str)) return names } -func (ta *temperatureArm) getThermalValues() []float64 { +func (ta *temperatureArm) getThermalValues(system unsafe.Pointer) []float64 { ioHIDServiceClientCopyEvent := common.GetFunc[common.IOHIDServiceClientCopyEventFunc](ta.ioKit, common.IOHIDServiceClientCopyEventSym) ioHIDEventGetFloatValue := common.GetFunc[common.IOHIDEventGetFloatValueFunc](ta.ioKit, common.IOHIDEventGetFloatValueSym) - system := ta.ioHIDEventSystemClientCreate(common.KCFAllocatorDefault) - ta.ioHIDEventSystemClientSetMatching(uintptr(system), uintptr(ta.sensors)) matchingsrvs := ta.ioHIDEventSystemClientCopyServices(uintptr(system)) if matchingsrvs == nil { return nil } + defer ta.cfRelease(uintptr(matchingsrvs)) count := ta.cfArrayGetCount(uintptr(matchingsrvs)) @@ -155,7 +158,6 @@ func (ta *temperatureArm) getThermalValues() []float64 { values = append(values, temp) } - ta.cfRelease(uintptr(matchingsrvs)) return values }