Bug: AppleSMC client matches nonexistent 'AppleSMCClient' IOKit service — all SMC telemetry dead #32

Closed
opened 2026-09-08 14:48:55 +01:00 by gronod · 0 comments
Owner

Purpose

The AppleSMC user-client connection can never open because the client matches the wrong IOKit service name, taking down all SMC-backed telemetry: CPU/core temperatures, component/heatsink temps, fan speeds, and power/voltage/current rails.

Symptoms (observed on Intel MacBook Air i5-8210Y, macOS 14)

  • CPU Temperature card: 0.0 °C package, 0 °C average, 0 °C peak.
  • Cooling Fans card: "No SMC fan sensors detected" — incorrect, the machine has a fan.
  • Power Draw & Rails: 0 W / 0 V / 0 A for every metric.
  • Component thermal matrix: empty.

Root Cause

Sources/Hardware/AppleSMC/MMAppleSMCClient.m:60:

CFMutableDictionaryRef matching = IOServiceMatching("AppleSMCClient");

The kernel service is AppleSMC, not AppleSMCClient — per ARCHITECTURE.md §3.1: IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("AppleSMC")). AppleSMCClient is the user-client class name, not the service name.

Consequence chain:

  1. IOServiceGetMatchingService returns IO_OBJECT_NULLopenWithError returns NO → _opened = NO, _connection = IO_OBJECT_NULL.
  2. isAvailable (MMAppleSMCClient.m:39) returns NO permanently.
  3. MMCPUThermalProvider, MMFanTelemetryProvider, MMComponentThermalProvider, and MMPowerTelemetryProvider all gate on _smcClient.isAvailable (e.g. MMPowerTelemetryProvider.m:84, MMFanTelemetryProvider.m:54) → they report unavailable and never emit telemetry.
  4. MMFanTelemetryProvider init bails early (if (!_smcClient.isAvailable) return at line 26) → _probedFanCount never probed → fans: [] → UI shows "No SMC fan sensors detected" (ContentView.swift:881).

Suggested Fix

  • Change the match string to @"AppleSMC".
  • readBytesForKey already retries openWithError when unavailable (MMAppleSMCClient.m:168-170), so the fix self-heals on the next sample — but consider making provider init paths resilient (e.g. MMFanTelemetryProvider should re-probe FNum when the client becomes available, since init may run before first successful open).
  • Verify on real Intel hardware: FNum, TC0P, F0Ac, PSTR/PDTR reads return non-nil.
  • Follow-up consideration: the alert engine sources batteryLevel from the SMC-gated power provider — the batteryHealth path (AppleSmartBattery) works independently of SMC and is a more reliable input for the low-battery rule.
  • Unit tests stay on mock SMC byte buffers per AGENTS.md §5.1 — do not assert live hardware reads in CI.

Acceptance Criteria

  • CPU package/core temperatures populate on Intel hardware.
  • Fan card lists real fans with live RPM, min/max/target.
  • Component thermal matrix populates.
  • Power draw and voltage/current rails show live values.
  • Thermal-dependent alert rules (CPU temp, fan stall) become functional.

Dependencies

  • None. Independent of the snapshot-key issues (#30, #31).
### Purpose The AppleSMC user-client connection can never open because the client matches the wrong IOKit service name, taking down all SMC-backed telemetry: CPU/core temperatures, component/heatsink temps, fan speeds, and power/voltage/current rails. ### Symptoms (observed on Intel MacBook Air i5-8210Y, macOS 14) - CPU Temperature card: 0.0 °C package, 0 °C average, 0 °C peak. - Cooling Fans card: "No SMC fan sensors detected" — incorrect, the machine has a fan. - Power Draw & Rails: 0 W / 0 V / 0 A for every metric. - Component thermal matrix: empty. ### Root Cause `Sources/Hardware/AppleSMC/MMAppleSMCClient.m:60`: ```objc CFMutableDictionaryRef matching = IOServiceMatching("AppleSMCClient"); ``` The kernel service is **`AppleSMC`**, not `AppleSMCClient` — per ARCHITECTURE.md §3.1: `IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("AppleSMC"))`. `AppleSMCClient` is the user-client class name, not the service name. Consequence chain: 1. `IOServiceGetMatchingService` returns `IO_OBJECT_NULL` → `openWithError` returns NO → `_opened = NO`, `_connection = IO_OBJECT_NULL`. 2. `isAvailable` (`MMAppleSMCClient.m:39`) returns NO permanently. 3. `MMCPUThermalProvider`, `MMFanTelemetryProvider`, `MMComponentThermalProvider`, and `MMPowerTelemetryProvider` all gate on `_smcClient.isAvailable` (e.g. `MMPowerTelemetryProvider.m:84`, `MMFanTelemetryProvider.m:54`) → they report unavailable and never emit telemetry. 4. `MMFanTelemetryProvider` init bails early (`if (!_smcClient.isAvailable) return` at line 26) → `_probedFanCount` never probed → `fans: []` → UI shows "No SMC fan sensors detected" (`ContentView.swift:881`). ### Suggested Fix - Change the match string to `@"AppleSMC"`. - `readBytesForKey` already retries `openWithError` when unavailable (`MMAppleSMCClient.m:168-170`), so the fix self-heals on the next sample — but consider making provider `init` paths resilient (e.g. `MMFanTelemetryProvider` should re-probe `FNum` when the client becomes available, since init may run before first successful open). - Verify on real Intel hardware: `FNum`, `TC0P`, `F0Ac`, `PSTR`/`PDTR` reads return non-nil. - Follow-up consideration: the alert engine sources `batteryLevel` from the SMC-gated power provider — the `batteryHealth` path (AppleSmartBattery) works independently of SMC and is a more reliable input for the low-battery rule. - Unit tests stay on mock SMC byte buffers per AGENTS.md §5.1 — do not assert live hardware reads in CI. ### Acceptance Criteria - [ ] CPU package/core temperatures populate on Intel hardware. - [ ] Fan card lists real fans with live RPM, min/max/target. - [ ] Component thermal matrix populates. - [ ] Power draw and voltage/current rails show live values. - [ ] Thermal-dependent alert rules (CPU temp, fan stall) become functional. ### Dependencies - None. Independent of the snapshot-key issues (#30, #31).
gronod added this to the M6: Bugfix & Stability milestone 2026-09-08 14:48:55 +01:00
gronod added the Bug/BackendKind/Bug
Priority
Critical
1
Project/Antigravity
labels 2026-09-08 14:49:12 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gronod/MacMonitor#32