From c21508d2237482ce27d3d2d5a333a3073b6ce4ca Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Sat, 8 May 2021 20:38:26 +0200 Subject: [PATCH] fix: fixed memory leak in the Sensors module on Apple Silicon (#417) --- Modules/Sensors/bridge.h | 9 ++++++ Modules/Sensors/reader.m | 47 +++++++++++++++++++++++++++++++ Modules/Sensors/readers.swift | 34 ++++------------------ Stats.xcodeproj/project.pbxproj | 4 +++ Stats/Supporting Files/Info.plist | 2 +- 5 files changed, 66 insertions(+), 30 deletions(-) create mode 100644 Modules/Sensors/reader.m diff --git a/Modules/Sensors/bridge.h b/Modules/Sensors/bridge.h index 11a19ba2..3a076b9b 100644 --- a/Modules/Sensors/bridge.h +++ b/Modules/Sensors/bridge.h @@ -21,11 +21,20 @@ typedef double IOHIDFloat; typedef float IOHIDFloat; #endif +#define IOHIDEventFieldBase(type) (type << 16) #define kIOHIDEventTypeTemperature 15 #define kIOHIDEventTypePower 25 +typedef enum AppleSiliconSensorType: NSUInteger { + temperature=1, + current=2, + voltage=3, +} AppleSiliconSensorType; + IOHIDEventSystemClientRef IOHIDEventSystemClientCreate(CFAllocatorRef allocator); int IOHIDEventSystemClientSetMatching(IOHIDEventSystemClientRef client, CFDictionaryRef match); IOHIDEventRef IOHIDServiceClientCopyEvent(IOHIDServiceClientRef, int64_t , int32_t, int64_t); CFStringRef IOHIDServiceClientCopyProperty(IOHIDServiceClientRef service, CFStringRef property); IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef event, int32_t field); + +NSDictionary*AppleSiliconSensors(int page, int usage, int32_t type); diff --git a/Modules/Sensors/reader.m b/Modules/Sensors/reader.m new file mode 100644 index 00000000..8a790524 --- /dev/null +++ b/Modules/Sensors/reader.m @@ -0,0 +1,47 @@ +// +// reader.m +// Sensors +// +// Created by Serhiy Mytrovtsiy on 06/05/2021. +// Using Swift 5.0. +// Running on macOS 10.15. +// +// Copyright © 2021 Serhiy Mytrovtsiy. All rights reserved. +// + +#import +#import "bridge.h" + +NSDictionary*AppleSiliconSensors(int32_t page, int32_t usage, int32_t type) { + NSDictionary* dictionary = @{@"PrimaryUsagePage":@(page),@"PrimaryUsage":@(usage)}; + + IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault); + IOHIDEventSystemClientSetMatching(system, (__bridge CFDictionaryRef)dictionary); + CFArrayRef services = IOHIDEventSystemClientCopyServices(system); + if (services == nil) { + return nil; + } + + NSMutableDictionary*dict = [NSMutableDictionary dictionary]; + for (int i = 0; i < CFArrayGetCount(services); i++) { + IOHIDServiceClientRef service = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(services, i); + NSString* name = CFBridgingRelease(IOHIDServiceClientCopyProperty(service, CFSTR("Product"))); + + IOHIDEventRef event = IOHIDServiceClientCopyEvent(service, type, 0, 0); + if (event == nil) { + continue; + } + + if (name && event) { + double value = IOHIDEventGetFloatValue(event, IOHIDEventFieldBase(type)); + dict[name]=@(value); + } + + CFRelease(event); + } + + CFRelease(services); + CFRelease(system); + + return dict; +} diff --git a/Modules/Sensors/readers.swift b/Modules/Sensors/readers.swift index fd18ddc4..b4f0b9e0 100644 --- a/Modules/Sensors/readers.swift +++ b/Modules/Sensors/readers.swift @@ -113,8 +113,8 @@ internal class AppleSilicon_SensorsReader: SensorsReader { } private func fetch(type: SensorType) { - var page: Int = 0 - var usage: Int = 0 + var page: Int32 = 0 + var usage: Int32 = 0 var eventType: Int32 = kIOHIDEventTypeTemperature // usagePage: @@ -147,33 +147,9 @@ internal class AppleSilicon_SensorsReader: SensorsReader { case .fan: break } - guard let client = IOHIDEventSystemClientCreate(kCFAllocatorDefault) else { - return - } - let system: IOHIDEventSystemClient = client.takeRetainedValue() - - let dict = createDeviceMatchingDictionary(usagePage: page, usage: usage) - IOHIDEventSystemClientSetMatching(system, dict) - - guard let services: CFArray = IOHIDEventSystemClientCopyServices(system) else { - return - } - - for i in 0..? = IOHIDServiceClientCopyProperty(service.pointee, "Product" as CFString) - - guard let nameCF = namePtr?.takeRetainedValue() else { - return - } - let name = nameCF as String - - if let eventPtr: IOHIDEventRef = IOHIDServiceClientCopyEvent(service.pointee, Int64(eventType), 0, 0) { - let value = IOHIDEventGetFloatValue(eventPtr, eventType << 16) - + if let list = AppleSiliconSensors(page, usage, eventType) { + list.forEach { (key, value) in + if let name = key as? String, let value = value as? Double { if self.cache.keys.contains(name) { self.cache[name]?.value = value } else { diff --git a/Stats.xcodeproj/project.pbxproj b/Stats.xcodeproj/project.pbxproj index f46fe45d..71a8aad9 100644 --- a/Stats.xcodeproj/project.pbxproj +++ b/Stats.xcodeproj/project.pbxproj @@ -99,6 +99,7 @@ 9AB14B7A248CEF4900DC6731 /* config.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9ABFF904248BEC0B00C9041A /* config.plist */; }; 9AB1572E25407F7B00671260 /* ModuleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AABEADD243FB13500668CB0 /* ModuleKit.framework */; }; 9AB1573D25407F7E00671260 /* StatsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A0C82DA24460F7200FAE3D4 /* StatsKit.framework */; }; + 9AB6D03926447CAA003215A5 /* reader.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AB6D03826447CAA003215A5 /* reader.m */; }; 9AB7FD7C246B48DB00387FDA /* settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AB7FD7B246B48DB00387FDA /* settings.swift */; }; 9ABFF8FD248BEBCB00C9041A /* Battery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9ABFF8F6248BEBCB00C9041A /* Battery.framework */; }; 9ABFF8FE248BEBCB00C9041A /* Battery.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9ABFF8F6248BEBCB00C9041A /* Battery.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -465,6 +466,7 @@ 9AABEAE9243FB15E00668CB0 /* module.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = module.swift; sourceTree = ""; }; 9AABEB79243FD26200668CB0 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 9AABEB7D243FDEF100668CB0 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 9AB6D03826447CAA003215A5 /* reader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = reader.m; sourceTree = ""; }; 9AB7FD7B246B48DB00387FDA /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = ""; }; 9ABFF8F6248BEBCB00C9041A /* Battery.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Battery.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9ABFF8F9248BEBCB00C9041A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -863,6 +865,7 @@ 9AE29AEC249A50960071B02D /* Info.plist */, 9AE29AF4249A52870071B02D /* config.plist */, 9A3616E82613C3D400D657B6 /* bridge.h */, + 9AB6D03826447CAA003215A5 /* reader.m */, ); path = Sensors; sourceTree = ""; @@ -1563,6 +1566,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9AB6D03926447CAA003215A5 /* reader.m in Sources */, 9AE29AFB249A53DC0071B02D /* readers.swift in Sources */, 9AE29AFC249A53DC0071B02D /* values.swift in Sources */, 9A58DE9E24B363D800716A9F /* popup.swift in Sources */, diff --git a/Stats/Supporting Files/Info.plist b/Stats/Supporting Files/Info.plist index b6e63253..6b51606a 100755 --- a/Stats/Supporting Files/Info.plist +++ b/Stats/Supporting Files/Info.plist @@ -17,7 +17,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 240 + 241 Description Simple macOS system monitor in your menu bar LSApplicationCategoryType