Repository navigation
Launch stalls for 10 s on macOS 27 (App Store build): system_profiler call blocks the main thread #178
Description
Description
On macOS 27, about one launch in seven of the Mac App Store build freezes for about 10 seconds before the window becomes usable. The delay is always the same length. It started with the update to macOS 27.0.1; launches were fast before.
The cause is deviceModelPretty(): it runs /usr/sbin/system_profiler -json SPHardwareDataType -detailLevel mini on every launch and waits for it with waitUntilExit() on the main thread. Under the App Sandbox, system_profiler on macOS 27 sometimes takes exactly 10 seconds to finish.
Steps to reproduce
- Install the Mac App Store build on macOS 27.
- Quit and relaunch Telegram several times.
Expected: the window is usable within a fraction of a second on every launch.
Actual: about one launch in seven freezes for about 10 seconds.
Environment
- macOS 27.2 (26B123), MacBook Pro (16-inch, 2023), Apple M2 Pro
- Telegram 13.1.0 (283357), Mac App Store build (sandboxed)
Analysis
Code locations (at 45d13c1):
TelegramSystem.swift#L25:deviceFromSystemProfiler()launchessystem_profilerand callswaitUntilExit()with no timeout.deviceModelPretty()calls it on every invocation; the result is not cached.AppDelegate.swift#L832:deviceModelPretty()is evaluated while buildingNetworkInitializationArguments, right beforeSharedAccountContextopens the postbox. The enclosing closure is delivered on the main queue (#L652), so the UI is blocked for the whole wait.ShareViewController.swift#L123: the share extension does the same.
Why system_profiler sometimes takes 10 seconds: since macOS 27, SPHardwareDataType queries the Activation Lock status from com.apple.icloud.findmydeviced. system_profiler inherits Telegram's App Sandbox, which denies that mach lookup. Usually both FindMyDevice calls fail at once and system_profiler exits within about 0.1 s. Sometimes the completion of the second call (isActivationLockedWithCompletion:) never arrives, and the hardware reporter waits for its fixed 10-second timeout. That part is an Apple bug, but it only hurts Telegram because the call is synchronous and on the launch path.
Telegram's own log during a slow launch (paths shortened, times relative to the first line):
+0.000 s AccountManager initialization took 40.06195068359375 ms
+10.187 s openPostbox, basePath: …/appstore/account-…/postbox, useCopy: false
System log in the same window, filtered to the system_profiler worker process (same time reference):
+0.052 s system_profiler[…] FRAMEWORK API: -[FMDFMMManager isActivationLockCapableWithCompletion:]
+0.052 s kernel Sandbox: system_profiler(…) deny(1) mach-lookup com.apple.icloud.findmydeviced
+0.052 s system_profiler[…] XPC error for isActivationLockCapableWithCompletion: 0
+0.052 s system_profiler[…] FRAMEWORK API: -[FMDFMMManager isActivationLockedWithCompletion:]
+10.054 s system_profiler[…] (SPPlatformReporter) Timed out waiting for the Activation Lock Status check
In fast launches, XPC error for isActivationLockedWithCompletion: 0 follows immediately and there is no timeout. Telegram continues about 0.1 s after the timeout line.
The stall also reproduces without Telegram, by denying only that lookup:
printf '(version 1)\n(allow default)\n(deny mach-lookup (global-name "com.apple.icloud.findmydeviced"))\n' > deny-fmd.sb
time sandbox-exec -f deny-fmd.sb /usr/sbin/system_profiler -json SPHardwareDataType -detailLevel mini
In 40 runs, one took 10.09 s, with the same log pattern as above.
Suggested fix
The device name does not change while the app is running, so it does not need a subprocess on every launch:
- Avoid
system_profilerentirely. On Apple Silicon the IORegistry entryIODeviceTree:/producthas aproduct-nameproperty (here: "MacBook Pro (16-inch, 2023)"), andsysctlbyname("machdep.cpu.brand_string")returns the chip ("Apple M2 Pro"). Both are instant and need no subprocess. I have not tested them inside the App Sandbox. - If
system_profilerstays: compute the name once, off the main thread, and give the process a short timeout with the existinghw.modelfallback.
Activity