Skip to content

refactor(ios): modernize kroll core with GCD#14395

Open
hansemannn wants to merge 8 commits intotidev:mainfrom
hansemannn:refactor/iosmodernization
Open

refactor(ios): modernize kroll core with GCD#14395
hansemannn wants to merge 8 commits intotidev:mainfrom
hansemannn:refactor/iosmodernization

Conversation

@hansemannn
Copy link
Collaborator

This pull request modernizes and improves thread safety and timer management throughout the TitaniumKit code base. The main changes replace legacy locking and timer APIs with more efficient and safer alternatives, update the timer manager to use GCD-based timers for better performance and accuracy, and refactor singleton and static initialization patterns for thread safety.

These changes collectively improve the reliability, safety, and maintainability of the TitaniumKit core, especially in multithreaded and timer-heavy scenarios. It is a follow-up of #14260 with a more detailed implementation plan for possible iterations. It also catches way more scenarios.

Note: This will not make apps 10x faster out of a sudden, but primarily improves debugging capabilities (with clear labels where which GCD ran). It still slightly improves app launch or opening more complex windows, where many TiProxy instances are created.

hansemannn and others added 4 commits February 22, 2026 23:09
Replace static recursive pthread_mutex_t with a serial dispatch queue
using dispatch_queue_set_specific for re-entrancy detection.

Fixes double-unlock bug in KrollEval invoke: and invokeWithResult:
where pthread_mutex_unlock was called twice when an exception occurred.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Invocation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace legacy locking primitives across 11 TitaniumKit source files:

- TiProxy: pthread_rwlock_t → concurrent dispatch queues with barriers
  for listener and dynprops access; OSAtomic → stdatomic for bridgeCount
- TiViewProxy: pthread_rwlock_t → concurrent dispatch queue for children;
  NSRecursiveLock → serial dispatch queue with re-entrancy for destroy
- ObjcProxy: pthread_rwlock_t → concurrent dispatch queue for listeners
- KrollCallback: NSLock → serial dispatch queue for callback registry
- ImageLoader: NSRecursiveLock → serial dispatch queue
- TiLayoutQueue: pthread_mutex_t → serial dispatch queue
- TiUIWindowProxy: NSCondition → dispatch_semaphore_t + serial queue

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@m1ga
Copy link
Contributor

m1ga commented Feb 23, 2026

Anything particular to test or is it more a: check if apps still work like before and don't crash?
A first quick run with this SDK leads to (iOS 26.1 simulator):

Triggered by Thread: 0, Dispatch Queue: org.appcelerator.kroll.entry

Exception Type:    EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000beaddc6bc6a8 -> 0x00003eaddc6bc6a8 (possible pointer authentication failure)
Exception Codes:   0x0000000000000001, 0x0000beaddc6bc6a8

Termination Reason:  Namespace SIGNAL, Code 11, Segmentation fault: 11
Terminating Process: exc handler [85392]


VM Region Info: 0x3eaddc6bc6a8 is not in any region.  Bytes after previous region: 68435411977897  Bytes before following region: 36636667951448
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      commpage (reserved)        1000000000-7000000000   [384.0G] ---/--- SM=NUL  reserved VM address space (unallocated)
--->  GAP OF 0x5f9000000000 BYTES
      MALLOC_NANO              600000000000-600020000000 [512.0M] rw-/rwx SM=PRV  

Thread 0 Crashed::  Dispatch queue: org.appcelerator.kroll.entry
0   libdispatch.dylib             	       0x1801c7a3c _dispatch_sync_f + 28
1   TitaniumKit                   	       0x10508cbb0 DestroyQueuePerform + 36 (TiViewProxy.m:29) [inlined]
2   TitaniumKit                   	       0x10508cbb0 -[TiViewProxy _destroy] + 112 (TiViewProxy.m:1571)
3   TitaniumKit                   	       0x1050a4908 -[TiProxy dealloc] + 24 (TiProxy.m:426)
4   TitaniumKit                   	       0x10508c8e0 -[TiViewProxy dealloc] + 104 (TiViewProxy.m:1514)
5   TitaniumKit                   	       0x1050720c0 -[KrollObject dealloc] + 48 (KrollObject.m:466)
6   TitaniumKit                   	       0x1050713e8 KrollFinalizer + 220 (KrollObject.m:117)
7   JavaScriptCore                	       0x199f77374 JSC::JSCallbackObject<JSC::JSNonFinalObject>::destroy(JSC::JSCell*) + 108
8   JavaScriptCore                	       0x19a68e460 JSC::IsoHeapCellType::finishSweep(JSC::MarkedBlock::Handle&, JSC::FreeList*) const + 3324
9   JavaScriptCore                	       0x19a694714 JSC::MarkedBlock::Handle::sweep(JSC::FreeList*) + 388
10  JavaScriptCore                	       0x19a6917bc JSC::LocalAllocator::tryAllocateIn(JSC::MarkedBlock::Handle*, unsigned long) + 40
11  JavaScriptCore                	       0x19a691494 JSC::LocalAllocator::allocateSlowCase(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) + 168
12  JavaScriptCore                	       0x199f88f30 JSC::JSCallbackObject<JSC::JSNonFinalObject>::create(JSC::JSGlobalObject*, JSC::Structure*, OpaqueJSClass*, void*) + 1000
13  JavaScriptCore                	       0x199f8b480 JSObjectMake + 92
14  TitaniumKit                   	       0x105071f84 -[KrollObject jsobject] + 72 (KrollObject.m:435)
15  TitaniumKit                   	       0x10507404c -[KrollObject applyGarbageCollectionSafeguard] + 48 (KrollObject.m:1308)
16  TitaniumKit                   	       0x105075da8 -[KrollBridge registerProxy:] + 84 (KrollBridge.m:492)
17  Fitness Plan                  	       0x1049293a4 __53-[TiUIListItemProxy initWithListViewProxy:inContext:]_block_invoke + 48 (TiUIListItemProxy.m:31)
18  libdispatch.dylib             	       0x1801db4b0 _dispatch_client_callout + 12
19  libdispatch.dylib             	       0x1801d1050 _dispatch_lane_barrier_sync_invoke_and_complete + 92
20  Fitness Plan                  	       0x104929350 -[TiUIListItemProxy initWithListViewProxy:inContext:] + 168 (TiUIListItemProxy.m:30)
21  Fitness Plan                  	       0x104914de0 -[TiUIListView tableView:cellForRowAtIndexPath:] + 632 (TiUIListView.m:1607)
22  UIKitCore                     	       0x18656881c -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 1376
23  UIKitCore                     	       0x18653b09c -[UITableView _updateVisibleCellsForRanges:createIfNecessary:] + 540
24  UIKitCore                     	       0x18653b690 -[UITableView _updateVisibleCellsNow:] + 1100
25  UIKitCore                     	       0x186555820 -[UITableView layoutSubviews] + 144
26  UIKitCore                     	       0x18554e2b4 0x18516f000 + 4059828
27  UIKitCore                     	       0x18554e648 0x18516f000 + 4060744
28  UIKitCore                     	       0x1868dba34 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2656
29  QuartzCore                    	       0x18c78e954 CA::Layer::perform_update_(CA::Layer*, CALayer*, unsigned int, CA::LayerUpdateReason, CA::Transaction*) + 452
30  QuartzCore                    	       0x18c78e1a4 CA::Layer::update_if_needed_(CA::Transaction*, CA::LayerUpdateReason) + 600
31  UIKitCore                     	       0x1868cbba0 -[UIView(Hierarchy) layoutBelowIfNeeded] + 312
32  UIKitCore                     	       0x185a744bc -[UINavigationController _layoutViewController:] + 824
33  UIKitCore                     	       0x185a6dd80 -[UINavigationController _layoutTopViewControllerLookForNested:] + 424
34  UIKitCore                     	       0x185a6c274 -[UINavigationController _didEndTransitionFromView:toView:wasCustom:] + 828
35  UIKitCore                     	       0x18649d300 -[_UIViewControllerTransitionConductor _startTransition:fromViewController:toViewController:] + 992
36  UIKitCore                     	       0x18649cbac -[_UIViewControllerTransitionConductor startDeferredTransitionIfNeeded] + 660
37  UIKitCore                     	       0x185a751d4 -[UINavigationController __viewWillLayoutSubviews] + 80
38  UIKitCore                     	       0x185a5b1c4 -[UILayoutContainerView layoutSubviews] + 172
39  UIKitCore                     	       0x18554e2b4 0x18516f000 + 4059828
40  UIKitCore                     	       0x18554e648 0x18516f000 + 4060744
41  UIKitCore                     	       0x1868dba34 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2656
42  QuartzCore                    	       0x18c78e954 CA::Layer::perform_update_(CA::Layer*, CALayer*, unsigned int, CA::LayerUpdateReason, CA::Transaction*) + 452
43  QuartzCore                    	       0x18c78e1a4 CA::Layer::update_if_needed_(CA::Transaction*, CA::LayerUpdateReason) + 600
44  QuartzCore                    	       0x18c799e34 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 152
45  QuartzCore                    	       0x18c6af794 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 544
46  QuartzCore                    	       0x18c6df6c8 CA::Transaction::commit() + 636
47  QuartzCore                    	       0x18c6e0f70 CA::Transaction::flush_as_runloop_observer(bool) + 68
48  UIKitCore                     	       0x18630d804 _UIApplicationFlushCATransaction + 48
49  UIKitCore                     	       0x18622a7c8 __setupUpdateSequence_block_invoke_2 + 372
50  UIKitCore                     	       0x1857f8634 _UIUpdateSequenceRunNext + 120
51  UIKitCore                     	       0x18622ac24 schedulerStepScheduledMainSectionContinue + 56
52  UpdateCycle                   	       0x24ffc62b4 UC::DriverCore::continueProcessing() + 80
53  CoreFoundation                	       0x1804563a4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
54  CoreFoundation                	       0x1804562ec __CFRunLoopDoSource0 + 168
55  CoreFoundation                	       0x180455ad4 __CFRunLoopDoSources0 + 312
56  CoreFoundation                	       0x180454c4c __CFRunLoopRun + 760
57  CoreFoundation                	       0x18044fcec _CFRunLoopRunSpecificWithOptions + 496
58  GraphicsServices              	       0x1926be9bc GSEventRunModal + 116
59  UIKitCore                     	       0x18630f0d8 -[UIApplication _run] + 772
60  UIKitCore                     	       0x186313300 UIApplicationMain + 124
61  Fitness Plan                  	       0x1048ac5c0 main + 824 (main.m:70)
62  ???                           	       0x1051913d0 ???
63  dyld                          	       0x1053a4d54 start + 7184

same app with 13.1.1 works fine.

@hansemannn
Copy link
Collaborator Author

Thanks! It still requires more testing, this one is AI powered on purpose - let's see how it works out :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants