You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[objective_c] Debug builds hang on iOS 27: assert-only _isValidClass calls objc_copyClassList, which deadlocks in realizeAllClasses() #3753
In debug builds, _isValidClass (lib/src/internal.dart) rebuilds its class cache with objc_copyClassList whenever a class is missing from _allClasses. That call realizes every Objective-C class in the process on the calling thread (the main thread here). On iOS 27 it never returns: the app freezes during startup, before its first screen. On iOS 26 the same scan completes after about 90 seconds of blank screen. Profile and release builds are unaffected because the check runs only under assert.
Versions
objective_c 9.5.0 (via path_provider_foundation 2.6.0). The check is unchanged in 9.6.2.
Flutter 3.41.8 stable, Xcode 27.1, iOS 27.0 simulator (iPhone 18 Pro). Also reproduced as a ~90 s stall on an iOS 26.0 simulator.
Evidence
sample of the hung process, 100 s after launch, 0% CPU, main thread in every one of 3,699 samples:
The 0% CPU means it is waiting, not working: realizing a class from AppIntentsServices appears to block while the main thread is inside the call (which is bound with isLeaf: true). We have not identified what it waits on.
Workarounds we found
Debug on an iOS 26 runtime, or profile/release on iOS 27.
--dart-flags=--no-enable-asserts is refused by the engine's allowlist, so asserts cannot be turned off for one app.
Suggestions
Avoid objc_copyClassList in the validity check (for example validate with object_getClass / class_getName on the specific pointer, or objc_lookUpClass by name), or
Do not realize all classes on the main thread, or let apps opt out of the debug check.
The reason it's written that way is that the function has to work even if the class pointer is not valid. If we call class_getName on an invalid class pointer, it's undefined behavior (and would likely crash), defeating the purpose of this function. But object_getClass already crashes if the object is not valid, so this check needs to be removed or rewritten.
I'll look into whether we can do a simpler sanity check of the pointer. Otherwise we should just remove this.
Activity
liamappelbe commentedon Oct 30, 2026
The reason it's written that way is that the function has to work even if the class pointer is not valid. If we call
class_getNameon an invalid class pointer, it's undefined behavior (and would likely crash), defeating the purpose of this function. Butobject_getClassalready crashes if the object is not valid, so this check needs to be removed or rewritten.I'll look into whether we can do a simpler sanity check of the pointer. Otherwise we should just remove this.