Pair Button + CFNetwork Crash Analysis¶
Date: 2026-04-12 (CFNetwork part RESOLVED, Pair button part still relevant) Status: CFNetwork crash fixed. Pair button mechanism described below is the path forward but needs to be implemented via the right protocol layer.
Part 1: CFNetwork Crash — RESOLVED¶
Original problem¶
CDS crashed with SIGSEGV in HTTPConnectionCache::timeoutIdleConnections() when
service connection actions ran. NULL+0x68 deref inside CFNetwork.
Root cause¶
interpose_xpc_remote_connection_create_with_remote_service was returning NULL
for any service not in our hardcoded list of 10 services. CFNetwork registered
NULL in HTTPConnectionCache and crashed during the idle-cleanup timer.
Fix applied¶
Parse all 74 services from the RSD Handshake Services dict into g_services[]
at init time. The interpose then has a real port for any service Xcode asks for,
and never returns NULL. See iosmux_xpc_proxy.m Handshake event handler.
This part of the document is kept for historical context only — the bug is gone.
Part 2: Pair Button Mechanism — STILL RELEVANT¶
Problem¶
Xcode shows "Pair" button even when DeviceInfo.pairingState is set to .paired. Clicking it triggers an XPC action flow that we currently can't satisfy.
Mechanism (verified by DVTCoreDeviceCore disassembly)¶
Xcode UI displays the device based on a computed deviceWindowCategory property
in DVTDeviceKit, which depends on three KVO properties of DVTCoreDevice_Impl:
deviceWindowCategory =
if hasConnection then connected_path (category 3 or 6 → no Pair button)
else disconnected_path (category 0 or 4 → shows Pair button)
hasConnection is computed:
_shadowUseAssertion is a CoreDevice.DeviceUsageAssertion? field on
DVTCoreDevice_Impl. It is set when Xcode's local
CoreDevice.RemoteDevice.acquireDeviceUsageAssertion(withReason:options:...)
returns success — which dispatches an AcquireBUsageAssertionActionDeclaration
through Mercury to CDS and waits for the reply.
Without a successful response to that action, _shadowUseAssertion stays nil →
hasConnection is false → device window category is "disconnected" → Xcode shows
the Pair button.
Implication¶
To make the Pair button disappear, we need CDS to respond successfully to the
acquireusageassertion action. The exact response format is the
CoreDevice.AcquireBUsageAssertionActionDeclaration.Output type — Codable struct,
internal fields not yet runtime-verified.
Action interception complication¶
Xcode↔CDS uses Mercury Codable XPCDictionary with mangledTypeName envelope, NOT
the flat CoreDevice.featureIdentifier dict format that pymobiledevice3 uses
against the iPhone. Filtering by a top-level string key is impossible on this
connection. See action-interception-full-picture.md for the synthesis and the
new strategy options.
Part 3: Missing DeviceInfo Fields — UNVERIFIED HYPOTHESIS¶
We currently set: name, productType, hardwareModel, marketingName, state, pairingState, visibilityClass, areDeveloperDiskImageServicesAvailable, preparednessState.
The following fields may also affect Xcode's device categorization. The list
comes from disassembling DVTCoreDeviceCore.DVTCoreDevice_Impl setters and
matching them to CoreDeviceProtocols.DeviceInfo fields. None of these have
been runtime-verified to actually change Xcode behavior.
| Field | Plausible value | Why it might matter |
|---|---|---|
| transportType | .localNetwork | Auto-pair + connection logic |
| platform | .iOS | UI classification |
| deviceType | .iPhone | UI icon/category |
| reality | .physical | vs virtual/simulated |
| osVersion | from Handshake | UI display |
| osBuild | from Handshake | Compatibility checks |
| udid | from Handshake | Identity cross-check |
| authenticationType | .manualPairing | Pairing flow type |
| developerModeStatus | .enabled | Skip developer mode prompt |
| bootState | .booted | Device is running |
| isMobileDeviceOnly | true | iOS device flag |
All of OSVersion / BuildVersion / UniqueDeviceID / ProductType / SerialNumber / DeviceClass / HardwarePlatform / ChipID / BoardId / UniqueChipID are available in the RSD Handshake Properties dict (46 keys total).
When to set these¶
Defer until after action interception is working. If acquireusageassertion
returning success is enough to make the Pair button disappear and CDS to consider
the device usable, the additional DeviceInfo fields may not be needed. If it
isn't enough, set them one at a time and observe.