Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ios13 -[ASTextKitContext initWithAttributedString:lineBreakMode:maximumNumberOfLines:exclusionPaths:constrainedSize:] deadlock appear in rare cases #1690

Open
CoderXL opened this issue Sep 28, 2019 · 28 comments
Assignees
Labels

Comments

@CoderXL
Copy link

CoderXL commented Sep 28, 2019

in ios13 we found -[ASTextKitContext initWithAttributedString:lineBreakMode:maximumNumberOfLines:exclusionPaths:constrainedSize:] will case a deadlock in rare cases
here is the call stacks in xcode when deadlock appears

Thread 1 Queue : com.apple.main-thread (serial)
#0 0x0000000184467cdc in __psynch_mutexwait ()
#1 0x000000018438a1a4 in _pthread_mutex_firstfit_lock_wait ()
#2 0x000000018438a114 in _pthread_mutex_firstfit_lock_slow$VARIANT$armv81 ()
#3 0x00000001844e94b0 in std::__1::mutex::lock() ()
#4 0x00000001016ffa2c in ASDN::Mutex::lock() at Pods/Texture/Source/Details/ASThread.h:166
#5 0x000000010183020c in std::__1::lock_guardASDN::Mutex::lock_guard(ASDN::Mutex&) at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__mutex_base:104
#6 0x000000010182fed0 in std::__1::lock_guardASDN::Mutex::lock_guard(ASDN::Mutex&) at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__mutex_base:104
#7 0x000000010182fb64 in ::-[ASTextKitContext initWithAttributedString:lineBreakMode:maximumNumberOfLines:exclusionPaths:constrainedSize:](NSAttributedString , NSLineBreakMode, NSUInteger, NSArray , CGSize) at Pods/Texture/Source/TextKit/ASTextKitContext.mm:44
#8 0x000000010183a164 in ::-[ASTextKitRenderer initWithTextKitAttributes:constrainedSize:](const ASTextKitAttributes &, CGSize) at Pods/Texture/Source/TextKit/ASTextKitRenderer.mm:63
#9 0x0000000101867a2c in rendererForAttributes(ASTextKitAttributes, CGSize) at Pods/Texture/Source/ASTextNode.mm:129
#10 0x00000001018692d0 in ::-ASTextNode _locked_rendererWithBounds: at Pods/Texture/Source/ASTextNode.mm:357
#11 0x00000001018698e4 in ::-ASTextNode calculateSizeThatFits: at Pods/Texture/Source/ASTextNode.mm:415
#12 0x000000010175c0c4 in ::-ASDisplayNode(ASLayoutSpec) calculateLayoutLayoutSpec: at Pods/Texture/Source/ASDisplayNode+LayoutSpec.mm:45
#13 0x0000000101770a04 in ::-ASDisplayNode calculateLayoutThatFits: at Pods/Texture/Source/ASDisplayNode.mm:1114
#14 0x000000010177083c in ::-[ASDisplayNode calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/ASDisplayNode.mm:1096
#15 0x00000001017566a4 in ::-ASDisplayNode(ASLayoutInternal) _u_measureNodeWithBoundsIfNecessary: at Pods/Texture/Source/ASDisplayNode+Layout.mm:371
#16 0x00000001017704d4 in ::-ASDisplayNode __layout at Pods/Texture/Source/ASDisplayNode.mm:1048
#17 0x00000001016d4220 in ::-_ASDisplayLayer layoutSublayers at Pods/Texture/Source/Details/_ASDisplayLayer.mm:99
#18 0x000000018afd495c in CA::Layer::layout_if_needed(CA::Transaction
) ()
#19 0x000000018afcfff8 in -[CALayer layoutIfNeeded] ()
#20 0x00000001017727a4 in ::-ASDisplayNode _recursivelyTriggerDisplayAndBlock: at Pods/Texture/Source/ASDisplayNode.mm:1464
#21 0x00000001017719cc in ::__49+[ASDisplayNode scheduleNodeForRecursiveDisplay:]_block_invoke_2(ASDisplayNode , BOOL) at Pods/Texture/Source/ASDisplayNode.mm:1323
#22 0x00000001017eb73c in ::-ASRunLoopQueue processQueue at Pods/Texture/Source/ASRunLoopQueue.mm:265
#23 0x00000001017eb1e4 in ::__56-[ASRunLoopQueue initWithRunLoop:retainObjects:handler:]_block_invoke(CFRunLoopObserverRef, CFRunLoopActivity) at Pods/Texture/Source/ASRunLoopQueue.mm:153
#24 0x00000001845ec4f8 in CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION ()
#25 0x00000001845e73e4 in __CFRunLoopDoObservers ()
#26 0x00000001845e79b0 in __CFRunLoopRun ()
#27 0x00000001845e716c in CFRunLoopRunSpecific ()
#28 0x000000018e41f328 in GSEventRunModal ()
#29 0x0000000188651d0c in UIApplicationMain ()
#30 0x0000000100c7fe44 in main at QingTui_iPhone/main.m:18
#31 0x0000000184472424 in start ()
JavaScriptCore bmalloc scavenger (6)#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x00000001844b97a8 in std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) ()
#3 0x00000001931c669c in void std::__1::condition_variable_any::wait<std::__1::unique_lockbmalloc::Mutex >(std::__1::unique_lockbmalloc::Mutex&) ()
#4 0x00000001931ca010 in bmalloc::Scavenger::threadRunLoop() ()
#5 0x00000001931c9cf8 in bmalloc::Scavenger::threadEntryPoint(bmalloc::Scavenger
) ()
#6 0x00000001931cb004 in void
std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_deletestd::__1::__thread_struct >, void ()(bmalloc::Scavenger), bmalloc::Scavenger*> >(void*) ()
#7 0x000000018438c1f0 in _pthread_start ()
com.apple.uikit.eventfetch-thread (7)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x0000000184927408 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#6 0x00000001849272e8 in -[NSRunLoop(NSRunLoop) runUntilDate:] ()
#7 0x00000001886e8aac in -[UIEventFetcher threadMain] ()
#8 0x0000000184a57884 in NSThread__start ()
#9 0x000000018438c1f0 in _pthread_start ()
com.apple.CFSocket.private (10)#0 0x0000000184468148 in __select ()
#1 0x00000001845fa3ec in __CFSocketManager ()
#2 0x000000018438c1f0 in _pthread_start ()
WCDB-checkpoint (11)#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x00000001844b97a8 in std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) ()
#3 0x00000001077ad3b0 in WCDB::TimedQueue<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >::waitUntilExpired(std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > const&)> const&, bool) at /Users/laiyoung/Documents/QT/QingTui_iPhones/670-master/PodPackage/PodPackage/Pods/WCDB/objc/WCDB/util/timed_queue.hpp:68
#4 0x00000001077ad20c in WCDB::Database::$_3::operator()(std::_1::shared_ptrWCDB::Handle&, WCDB::Error&) const::'lambda'(WCDB::Handle*, int, void*)::operator()(WCDB::Handle*, int, void*) const::'lambda'()::operator()() const at /Users/laiyoung/Documents/QT/QingTui_iPhones/670-master/PodPackage/PodPackage/Pods/WCDB/objc/WCDB/core/database_config.cpp:214
#5 0x00000001077ad18c in decltype(std::__1::forward<WCDB::Database::$_3::operator()(std::__1::shared_ptrWCDB::Handle&, WCDB::Error&) const::'lambda'(WCDB::Handle*, int, void*)::operator()(WCDB::Handle*, int, void*) const::'lambda'()>(fp)()) std::__1::__invoke<WCDB::Database::$_3::operator()(std::__1::shared_ptrWCDB::Handle&, WCDB::Error&) const::'lambda'(WCDB::Handle*, int, void*)::operator()(WCDB::Handle*, int, void*) const::'lambda'()>(WCDB::Database::$_3::operator()(std::__1::shared_ptrWCDB::Handle&, WCDB::Error&) const::'lambda'(WCDB::Handle*, int, void*)::operator()(WCDB::Handle*, int, void*) const::'lambda'()&&) at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/type_traits:4339
#6 0x00000001077ad120 in void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_deletestd::__1::__thread_struct >, WCDB::Database::$_3::operator()(std::__1::shared_ptrWCDB::Handle&, WCDB::Error&) const::'lambda'(WCDB::Handle*, int, void*)::operator()(WCDB::Handle*, int, void*) const::'lambda'()>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_deletestd::__1::__thread_struct >, WCDB::Database::$_3::operator()(std::__1::shared_ptrWCDB::Handle&, WCDB::Error&) const::'lambda'(WCDB::Handle*, int, void*)::operator()(WCDB::Handle*, int, void*) const::'lambda'()>&, std::__1::__tuple_indices<>) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/thread:342
#7 0x00000001077ad11c in void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_deletestd::__1::__thread_struct >, WCDB::Database::$_3::operator()(std::__1::shared_ptrWCDB::Handle&, WCDB::Error&) const::'lambda'(WCDB::Handle*, int, void*)::operator()(WCDB::Handle*, int, void*) const::'lambda'()> >(void*) at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/thread:352
#8 0x000000018438c1f0 in _pthread_start ()
com.apple.CoreMotion.MotionThread (12)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x00000001845e7eb8 in CFRunLoopRun ()
#6 0x0000000190ea7b24 in ___lldb_unnamed_symbol4960$$CoreMotion ()
#7 0x000000018438c1f0 in _pthread_start ()
com.squareup.SocketRocket.NetworkThread (21)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x0000000184927408 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#6 0x0000000107720ea8 in -[_SRRunLoopThread main] at Pods/SocketRocket/SocketRocket/Classes/SRWebSocket.m:1923
#7 0x0000000184a57884 in NSThread__start ()
#8 0x000000018438c1f0 in _pthread_start ()
com.apple.NSURLConnectionLoader (22)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x000000018784b3a4 in ___lldb_unnamed_symbol3$$CFNetwork ()
#6 0x0000000184a57884 in NSThread__start ()
#7 0x000000018438c1f0 in _pthread_start ()
GCDAsyncSocket-CFStream (23)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x0000000184927408 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#6 0x0000000101c6696c in +[GCDAsyncSocket cfstreamThread] at /var/folders/9j/ssspm2w932v7_plv6f3q39p80000gp/T/cocoapods-vs5b050w/Pods/Dynamic/CocoaAsyncSocket/Source/GCD/GCDAsyncSocket.m:7601
#7 0x0000000184a57884 in NSThread__start ()
#8 0x000000018438c1f0 in _pthread_start ()
com.autonavi.AMapLocationThread (42)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x0000000184927408 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#6 0x0000000184960f78 in -[NSRunLoop(NSRunLoop) run] ()
#7 0x0000000102d9a1d8 in +[AMapLocationCLMDelegate threadEntryPoint:] ()
#8 0x0000000184a57884 in NSThread__start ()
#9 0x000000018438c1f0 in _pthread_start ()
AMapNetwork (43)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x0000000184927408 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#6 0x0000000184960f78 in -[NSRunLoop(NSRunLoop) run] ()
#7 0x0000000102d86d60 in +[AMapNetworkOperation networkRequestThreadEntryPoint:] ()
#8 0x0000000184a57884 in NSThread__start ()
#9 0x000000018438c1f0 in _pthread_start ()
Thread 44#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x0000000103187728 in native_event_wait ()
#3 0x0000000103187b54 in internal_MSPThread_WaitMessages ()
#4 0x00000001031879c8 in MSPThread_WaitMessages ()
#5 0x00000001031a9134 in socket_main ()
#6 0x0000000103188b5c in ThreadEntryHook ()
#7 0x000000018438c1f0 in _pthread_start ()
Thread 45#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x0000000103187728 in native_event_wait ()
#3 0x00000001031563d4 in dns_main ()
#4 0x000000018438c1f0 in _pthread_start ()
Thread 46#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x0000000103187728 in native_event_wait ()
#3 0x0000000103187b54 in internal_MSPThread_WaitMessages ()
#4 0x00000001031879c8 in MSPThread_WaitMessages ()
#5 0x00000001031d27a0 in iFLYlua_engine_main ()
#6 0x0000000103188b5c in ThreadEntryHook ()
#7 0x000000018438c1f0 in _pthread_start ()
Thread 47#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x0000000103187728 in native_event_wait ()
#3 0x0000000103187b54 in internal_MSPThread_WaitMessages ()
#4 0x00000001031879c8 in MSPThread_WaitMessages ()
#5 0x00000001031d27a0 in iFLYlua_engine_main ()
#6 0x0000000103188b5c in ThreadEntryHook ()
#7 0x000000018438c1f0 in _pthread_start ()
Thread 48#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x0000000103187728 in native_event_wait ()
#3 0x0000000103187b54 in internal_MSPThread_WaitMessages ()
#4 0x00000001031879c8 in MSPThread_WaitMessages ()
#5 0x00000001031d27a0 in iFLYlua_engine_main ()
#6 0x0000000103188b5c in ThreadEntryHook ()
#7 0x000000018438c1f0 in _pthread_start ()
Thread 49#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x0000000103187728 in native_event_wait ()
#3 0x0000000103187b54 in internal_MSPThread_WaitMessages ()
#4 0x00000001031879c8 in MSPThread_WaitMessages ()
#5 0x00000001031d27a0 in iFLYlua_engine_main ()
#6 0x0000000103188b5c in ThreadEntryHook ()
#7 0x000000018438c1f0 in _pthread_start ()
Thread 50#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x0000000103187728 in native_event_wait ()
#3 0x0000000103187b54 in internal_MSPThread_WaitMessages ()
#4 0x0000000103188bf0 in ThreadEntryHook ()
#5 0x000000018438c1f0 in _pthread_start ()
MainRunloopMonitor (57)#0 0x0000000184446648 in semaphore_timedwait_trap ()
#1 0x000000010865f390 in _dispatch_sema4_timedwait ()
#2 0x000000010865f914 in _dispatch_semaphore_wait_slow ()
#3 0x0000000100cb12e4 in -[BLYMainRunloopMonitorManager monitorThreadRun] ()
#4 0x0000000184a57884 in NSThread__start ()
#5 0x000000018438c1f0 in _pthread_start ()
WebThread (58)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x000000018c474434 in RunWebThread(void*) ()
#6 0x000000018438c1f0 in _pthread_start ()
Thread 84#0 0x0000000184468a74 in __workq_kernreturn ()
com.facebook.react.JavaScript (99)#0 0x00000001844465f4 in mach_msg_trap ()
#1 0x0000000184445a60 in mach_msg ()
#2 0x00000001845ec918 in __CFRunLoopServiceMachPort ()
#3 0x00000001845e7a38 in __CFRunLoopRun ()
#4 0x00000001845e716c in CFRunLoopRunSpecific ()
#5 0x0000000106601ff0 in ::+RCTCxxBridge runRunLoop at /node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm:249
#6 0x0000000184a57884 in NSThread__start ()
#7 0x000000018438c1f0 in _pthread_start ()
Thread 115 Queue : org.AsyncDisplayKit.ASDataController.editingTransactionQueue:0x283a943c0 (serial)
#0 0x00000001844688b0 in __ulock_wait ()
#1 0x000000010865f720 in _dlock_wait ()
#2 0x000000010865fa90 in _dispatch_group_wait_slow ()
#3 0x000000010174f210 in ::ASDispatchApply(size_t, dispatch_queue_t, NSUInteger, void (^)(size_t)) at Pods/Texture/Source/Private/ASDispatch.mm:34
#4 0x00000001017418e0 in ::-[ASDataController _allocateNodesFromElements:](NSArray ) at Pods/Texture/Source/Details/ASDataController.mm:164
#5 0x0000000101746814 in ::__40-[ASDataController updateWithChangeSet:]_block_invoke.182() at Pods/Texture/Source/Details/ASDataController.mm:659
#6 0x000000010865d8ac in _dispatch_call_block_and_release ()
#7 0x000000010865ec88 in _dispatch_client_callout ()
#8 0x0000000108665df0 in _dispatch_lane_serial_drain ()
#9 0x0000000108666794 in _dispatch_lane_invoke ()
#10 0x0000000108671b88 in _dispatch_workloop_worker_thread ()
#11 0x000000018438cfa8 in _pthread_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0 0x000000010869174c in _dispatch_introspection_queue_item_enqueue_hook ()
#1 0x00000001086603f0 in dispatch_group_async ()
#2 0x0000000101745f98 in ::-[ASDataController updateWithChangeSet:](_ASHierarchyChangeSet ) at Pods/Texture/Source/Details/ASDataController.mm:640
#3 0x0000000101818804 in ::-[ASTableView endUpdatesAnimated:completion:](BOOL, void (^)(BOOL)) at Pods/Texture/Source/ASTableView.mm:725
#4 0x0000000101810ae0 in ::-[ASTableNode performBatchAnimated:updates:completion:](BOOL, void (^)(), void (^)(BOOL)) at Pods/Texture/Source/ASTableNode.mm:748
#5 0x0000000104f7f804 in -[QTMessageViewController messageTableUpdateWithRemoveIndexPaths:insertIndexPaths:scrollToIndex:atScrollPosition:animation:completeBlock:] at /Classes/Chat/MessageVC/QTMessageViewController.m:1416
#6 0x0000000104f520f8 in __78-[QTMessageVCModel processMessages:needClearLocal:isNewMessage:scrollToFirst:]_block_invoke_2 at /Classes/Chat/MessageVC/QTMessageVCModel.m:1695
#7 0x000000010865d8ac in _dispatch_call_block_and_release ()
#8 0x000000010865ec88 in _dispatch_client_callout ()
#9 0x000000010866cce8 in _dispatch_main_queue_callback_4CF ()
#10 0x00000001845ecc74 in CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE ()
#11 0x00000001845e7c68 in __CFRunLoopRun ()
#12 0x00000001845e716c in CFRunLoopRunSpecific ()
#13 0x000000018e41f328 in GSEventRunModal ()
#14 0x0000000188651d0c in UIApplicationMain ()
#15 0x0000000100c7fe44 in main at QingTui_iPhone/main.m:18
#16 0x0000000184472424 in start ()
Enqueued from com.qingtui.message (Thread 133) Queue : com.qingtui.message (serial)
#0 0x000000010869174c in _dispatch_introspection_queue_item_enqueue_hook ()
#1 0x00000001086630dc in dispatch_async ()
#2 0x0000000104f37d28 in dispatch_async_on_main_queue at Pods/QTCocoa/QTCocoa/Classes/System/Dispatch/QTDispatch.h:33
#3 0x0000000104f512cc in -[QTMessageVCModel processMessages:needClearLocal:isNewMessage:scrollToFirst:] at /Classes/Chat/MessageVC/QTMessageVCModel.m:1689
#4 0x0000000104f4f644 in __33-[QTMessageVCModel loadMessages:]_block_invoke at /Classes/Chat/MessageVC/QTMessageVCModel.m:1542
#5 0x000000010865d8ac in _dispatch_call_block_and_release ()
#6 0x000000010865ec88 in _dispatch_client_callout ()
#7 0x0000000108665bf8 in _dispatch_lane_serial_drain ()
#8 0x0000000108666794 in _dispatch_lane_invoke ()
#9 0x0000000108671b88 in _dispatch_workloop_worker_thread ()
#10 0x000000018438cfa8 in _pthread_wqthread ()
#11 0x000000018438fae4 in start_wqthread ()
Enqueued from com.qingtui.message.chat (Thread 161) Queue : com.qingtui.message.chat (serial)
#0 0x000000010869174c in _dispatch_introspection_queue_item_enqueue_hook ()
#1 0x00000001086630dc in dispatch_async ()
#2 0x0000000104f4f3f4 in -[QTMessageVCModel loadMessages:] at /Classes/Chat/MessageVC/QTMessageVCModel.m:1535
#3 0x0000000104f4be6c in __32-[QTMessageVCModel loadChatInfo]_block_invoke at /Classes/Chat/MessageVC/QTMessageVCModel.m:1381
#4 0x000000010865d8ac in _dispatch_call_block_and_release ()
#5 0x000000010865ec88 in _dispatch_client_callout ()
#6 0x0000000108665bf8 in _dispatch_lane_serial_drain ()
#7 0x0000000108666794 in _dispatch_lane_invoke ()
#8 0x0000000108671b88 in _dispatch_workloop_worker_thread ()
#9 0x000000018438cfa8 in _pthread_wqthread ()
#10 0x000000018438fae4 in start_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0 0x000000010869174c in _dispatch_introspection_queue_item_enqueue_hook ()
#1 0x00000001086630dc in dispatch_async ()
#2 0x0000000104f4ba24 in -[QTMessageVCModel loadChatInfo] at /Classes/Chat/MessageVC/QTMessageVCModel.m:1356
#3 0x0000000104f36768 in +[QTMessageVCModel modelWithViewController:chatId:chatType:domain:] at /Classes/Chat/MessageVC/QTMessageVCModel.m:77
#4 0x0000000104f5f918 in -[QTMessageViewController viewDidLoad] at /Classes/Chat/MessageVC/QTMessageViewController.m:243
#5 0x000000018804ade0 in -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] ()
#6 0x000000018804f8a0 in -[UIViewController loadViewIfRequired] ()
#7 0x000000018804fca8 in -[UIViewController view] ()
#8 0x0000000187faf96c in -[UINavigationController _startCustomTransition:] ()
#9 0x0000000187fc2ef0 in -[UINavigationController _startDeferredTransitionIfNeeded:] ()
#10 0x0000000187fc43f4 in -[UINavigationController __viewWillLayoutSubviews] ()
#11 0x0000000187fa81c8 in -[UILayoutContainerView layoutSubviews] ()
#12 0x0000000188ad6d3c in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#13 0x000000018afd012c in -[CALayer layoutSublayers] ()
#14 0x000000018afd495c in CA::Layer::layout_if_needed(CA::Transaction
) ()
#15 0x000000018afe0350 in CA::Layer::layout_and_display_if_needed(CA::Transaction
) ()
#16 0x000000018af28edc in CA::Context::commit_transaction(CA::Transaction*, double) ()
#17 0x000000018af52e44 in CA::Transaction::commit() ()
#18 0x000000018867a84c in _afterCACommitHandler ()
#19 0x00000001845ec4f8 in CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION ()
#20 0x00000001845e73e4 in __CFRunLoopDoObservers ()
#21 0x00000001845e79b0 in __CFRunLoopRun ()
#22 0x00000001845e716c in CFRunLoopRunSpecific ()
#23 0x000000018e41f328 in GSEventRunModal ()
#24 0x0000000188651d0c in UIApplicationMain ()
#25 0x0000000100c7fe44 in main at QingTui_iPhone/main.m:18
#26 0x0000000184472424 in start ()
Thread 131#0 0x000000018438fadc in start_wqthread ()
Thread 133 Queue : com.qingtui.message (serial)
#0 0x0000000184446630 in semaphore_wait_trap ()
#1 0x000000010865f314 in _dispatch_sema4_wait ()
#2 0x000000010865f958 in _dispatch_semaphore_wait_slow ()
#3 0x0000000104f512dc in -[QTMessageVCModel processMessages:needClearLocal:isNewMessage:scrollToFirst:] at /Classes/Chat/MessageVC/QTMessageVCModel.m:1700
#4 0x0000000104f4f644 in __33-[QTMessageVCModel loadMessages:]_block_invoke at /Classes/Chat/MessageVC/QTMessageVCModel.m:1542
#5 0x000000010865d8ac in _dispatch_call_block_and_release ()
#6 0x000000010865ec88 in _dispatch_client_callout ()
#7 0x0000000108665bf8 in _dispatch_lane_serial_drain ()
#8 0x0000000108666794 in _dispatch_lane_invoke ()
#9 0x0000000108671b88 in _dispatch_workloop_worker_thread ()
#10 0x000000018438cfa8 in _pthread_wqthread ()
Enqueued from com.qingtui.message.chat (Thread 161) Queue : com.qingtui.message.chat (serial)
#0 0x000000010869174c in _dispatch_introspection_queue_item_enqueue_hook ()
#1 0x00000001086630dc in dispatch_async ()
#2 0x0000000104f4f3f4 in -[QTMessageVCModel loadMessages:] at /Classes/Chat/MessageVC/QTMessageVCModel.m:1535
#3 0x0000000104f4be6c in __32-[QTMessageVCModel loadChatInfo]_block_invoke at /Classes/Chat/MessageVC/QTMessageVCModel.m:1381
#4 0x000000010865d8ac in _dispatch_call_block_and_release ()
#5 0x000000010865ec88 in _dispatch_client_callout ()
#6 0x0000000108665bf8 in _dispatch_lane_serial_drain ()
#7 0x0000000108666794 in _dispatch_lane_invoke ()
#8 0x0000000108671b88 in _dispatch_workloop_worker_thread ()
#9 0x000000018438cfa8 in _pthread_wqthread ()
#10 0x000000018438fae4 in start_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0 0x000000010869174c in _dispatch_introspection_queue_item_enqueue_hook ()
#1 0x00000001086630dc in dispatch_async ()
#2 0x0000000104f4ba24 in -[QTMessageVCModel loadChatInfo] at /Classes/Chat/MessageVC/QTMessageVCModel.m:1356
#3 0x0000000104f36768 in +[QTMessageVCModel modelWithViewController:chatId:chatType:domain:] at /Classes/Chat/MessageVC/QTMessageVCModel.m:77
#4 0x0000000104f5f918 in -[QTMessageViewController viewDidLoad] at /Classes/Chat/MessageVC/QTMessageViewController.m:243
#5 0x000000018804ade0 in -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] ()
#6 0x000000018804f8a0 in -[UIViewController loadViewIfRequired] ()
#7 0x000000018804fca8 in -[UIViewController view] ()
#8 0x0000000187faf96c in -[UINavigationController _startCustomTransition:] ()
#9 0x0000000187fc2ef0 in -[UINavigationController _startDeferredTransitionIfNeeded:] ()
#10 0x0000000187fc43f4 in -[UINavigationController __viewWillLayoutSubviews] ()
#11 0x0000000187fa81c8 in -[UILayoutContainerView layoutSubviews] ()
#12 0x0000000188ad6d3c in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#13 0x000000018afd012c in -[CALayer layoutSublayers] ()
#14 0x000000018afd495c in CA::Layer::layout_if_needed(CA::Transaction*) ()
#15 0x000000018afe0350 in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#16 0x000000018af28edc in CA::Context::commit_transaction(CA::Transaction*, double) ()
#17 0x000000018af52e44 in CA::Transaction::commit() ()
#18 0x000000018867a84c in _afterCACommitHandler ()
#19 0x00000001845ec4f8 in CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION ()
#20 0x00000001845e73e4 in __CFRunLoopDoObservers ()
#21 0x00000001845e79b0 in __CFRunLoopRun ()
#22 0x00000001845e716c in CFRunLoopRunSpecific ()
#23 0x000000018e41f328 in GSEventRunModal ()
#24 0x0000000188651d0c in UIApplicationMain ()
#25 0x0000000100c7fe44 in main at QingTui_iPhone/main.m:18
#26 0x0000000184472424 in start ()
Thread 135 Queue : com.apple.root.user-initiated-qos (concurrent)
#0 0x0000000184467c8c in __psynch_cvwait ()
#1 0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2 0x00000001849b22e4 in -[NSOperation waitUntilFinished] ()
#3 0x000000018494e8c8 in -[__NSObserver _doit:] ()
#4 0x00000001845ca9ac in CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER ()
#5 0x00000001845ca9f4 in ___CFXRegistrationPost1_block_invoke ()
#6 0x00000001845c9d54 in _CFXRegistrationPost1 ()
#7 0x00000001845c9a20 in ___CFXNotificationPost_block_invoke ()
#8 0x0000000184545d38 in -[_CFXNotificationRegistrar find:object:observer:enumerator:] ()
#9 0x00000001845c9370 in _CFXNotificationPost ()
#10 0x0000000184925cf8 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#11 0x0000000187ba2b44 in -[NSTextStorage processEditing] ()
#12 0x0000000187ba337c in -[NSTextStorage edited:range:changeInLength:] ()
#13 0x0000000184979d60 in -[NSConcreteMutableAttributedString replaceCharactersInRange:withAttributedString:] ()
#14 0x0000000187c241ac in __71-[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:]_block_invoke ()
#15 0x0000000187c23ddc in __NSConcreteTextStorageLockedForwarding ()
#16 0x0000000187ba90e4 in -[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:] ()
#17 0x000000010182fc74 in ::-[ASTextKitContext initWithAttributedString:lineBreakMode:maximumNumberOfLines:exclusionPaths:constrainedSize:](NSAttributedString *, NSLineBreakMode, NSUInteger, NSArray *, CGSize) at Pods/Texture/Source/TextKit/ASTextKitContext.mm:58
#18 0x000000010183a164 in ::-[ASTextKitRenderer initWithTextKitAttributes:constrainedSize:](const ASTextKitAttributes &, CGSize) at Pods/Texture/Source/TextKit/ASTextKitRenderer.mm:63
#19 0x0000000101867a2c in rendererForAttributes(ASTextKitAttributes, CGSize) at Pods/Texture/Source/ASTextNode.mm:129
#20 0x00000001018692d0 in ::-ASTextNode _locked_rendererWithBounds: at Pods/Texture/Source/ASTextNode.mm:357
#21 0x00000001018698e4 in ::-ASTextNode calculateSizeThatFits: at Pods/Texture/Source/ASTextNode.mm:415
#22 0x000000010175c0c4 in ::-ASDisplayNode(ASLayoutSpec) calculateLayoutLayoutSpec: at Pods/Texture/Source/ASDisplayNode+LayoutSpec.mm:45
#23 0x0000000101770a04 in ::-ASDisplayNode calculateLayoutThatFits: at Pods/Texture/Source/ASDisplayNode.mm:1114
#24 0x000000010177083c in ::-[ASDisplayNode calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/ASDisplayNode.mm:1096
#25 0x0000000101754974 in ::-[ASDisplayNode(ASLayoutElement) layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/ASDisplayNode+Layout.mm:88
#26 0x00000001017fab08 in crossChildLayout(ASStackLayoutSpecChild const&, ASStackLayoutSpecStyle const&, double, double, double, double, CGSize) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:65
#27 0x00000001017fa944 in ::___ZL43layoutItemsAlongUnconstrainedStackDimensionRNSt3__16vectorI21ASStackLayoutSpecItemNS_9allocatorIS1_EEEERK22ASStackLayoutSpecStylebRK11ASSizeRange6CGSizeb_block_invoke(size_t) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:689
#28 0x00000001017fa6a8 in dispatchApplyIfNeeded(unsigned long, bool, void (unsigned long) block_pointer) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:84
#29 0x00000001017f923c in layoutItemsAlongUnconstrainedStackDimension(std::__1::vector<ASStackLayoutSpecItem, std::__1::allocator >&, ASStackLayoutSpecStyle const&, bool, ASSizeRange const&, CGSize, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:684
#30 0x00000001017f8d08 in ASStackUnpositionedLayout::compute(std::__1::vector<ASStackLayoutSpecChild, std::__1::allocator > const&, ASStackLayoutSpecStyle const&, ASSizeRange const&, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:726
#31 0x00000001017f1ef8 in ::-ASStackLayoutSpec calculateLayoutThatFits: at Pods/Texture/Source/Layout/ASStackLayoutSpec.mm:148
#32 0x00000001017b2004 in ::-[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#33 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#34 0x00000001017fab08 in crossChildLayout(ASStackLayoutSpecChild const&, ASStackLayoutSpecStyle const&, double, double, double, double, CGSize) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:65
#35 0x00000001017fa944 in ::___ZL43layoutItemsAlongUnconstrainedStackDimensionRNSt3__16vectorI21ASStackLayoutSpecItemNS_9allocatorIS1_EEEERK22ASStackLayoutSpecStylebRK11ASSizeRange6CGSizeb_block_invoke(size_t) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:689
#36 0x00000001017fa6a8 in dispatchApplyIfNeeded(unsigned long, bool, void (unsigned long) block_pointer) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:84
#37 0x00000001017f923c in layoutItemsAlongUnconstrainedStackDimension(std::__1::vector<ASStackLayoutSpecItem, std::__1::allocator >&, ASStackLayoutSpecStyle const&, bool, ASSizeRange const&, CGSize, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:684
#38 0x00000001017f8d08 in ASStackUnpositionedLayout::compute(std::__1::vector<ASStackLayoutSpecChild, std::__1::allocator > const&, ASStackLayoutSpecStyle const&, ASSizeRange const&, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:726
#39 0x00000001017f1ef8 in ::-ASStackLayoutSpec calculateLayoutThatFits: at Pods/Texture/Source/Layout/ASStackLayoutSpec.mm:148
#40 0x00000001017b2004 in ::-[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#41 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#42 0x000000010179cb84 in ::-[ASInsetLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASInsetLayoutSpec.mm:102
#43 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#44 0x00000001016fc1f0 in ::-[ASBackgroundLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASBackgroundLayoutSpec.mm:50
#45 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#46 0x00000001017fab08 in crossChildLayout(ASStackLayoutSpecChild const&, ASStackLayoutSpecStyle const&, double, double, double, double, CGSize) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:65
#47 0x00000001017fa944 in ::___ZL43layoutItemsAlongUnconstrainedStackDimensionRNSt3__16vectorI21ASStackLayoutSpecItemNS_9allocatorIS1_EEEERK22ASStackLayoutSpecStylebRK11ASSizeRange6CGSizeb_block_invoke(size_t) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:689
#48 0x00000001017fa654 in dispatchApplyIfNeeded(unsigned long, bool, void (unsigned long) block_pointer) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:77
#49 0x00000001017f923c in layoutItemsAlongUnconstrainedStackDimension(std::__1::vector<ASStackLayoutSpecItem, std::__1::allocator >&, ASStackLayoutSpecStyle const&, bool, ASSizeRange const&, CGSize, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:684
#50 0x00000001017f8d08 in ASStackUnpositionedLayout::compute(std::__1::vector<ASStackLayoutSpecChild, std::__1::allocator > const&, ASStackLayoutSpecStyle const&, ASSizeRange const&, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:726
#51 0x00000001017f1ef8 in ::-ASStackLayoutSpec calculateLayoutThatFits: at Pods/Texture/Source/Layout/ASStackLayoutSpec.mm:148
#52 0x00000001017b2004 in ::-[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#53 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#54 0x000000010179cb84 in ::-[ASInsetLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASInsetLayoutSpec.mm:102
#55 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#56 0x00000001017fab08 in crossChildLayout(ASStackLayoutSpecChild const&, ASStackLayoutSpecStyle const&, double, double, double, double, CGSize) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:65
#57 0x00000001017fa944 in ::___ZL43layoutItemsAlongUnconstrainedStackDimensionRNSt3__16vectorI21ASStackLayoutSpecItemNS_9allocatorIS1_EEEERK22ASStackLayoutSpecStylebRK11ASSizeRange6CGSizeb_block_invoke(size_t) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:689
#58 0x00000001017fa654 in dispatchApplyIfNeeded(unsigned long, bool, void (unsigned long) block_pointer) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:77
#59 0x00000001017f923c in layoutItemsAlongUnconstrainedStackDimension(std::__1::vector<ASStackLayoutSpecItem, std::__1::allocator >&, ASStackLayoutSpecStyle const&, bool, ASSizeRange const&, CGSize, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:684
#60 0x00000001017f8d08 in ASStackUnpositionedLayout::compute(std::__1::vector<ASStackLayoutSpecChild, std::__1::allocator > const&, ASStackLayoutSpecStyle const&, ASSizeRange const&, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:726
#61 0x00000001017f1ef8 in ::-ASStackLayoutSpec calculateLayoutThatFits: at Pods/Texture/Source/Layout/ASStackLayoutSpec.mm:148
#62 0x00000001017b2004 in ::-[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#63 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#64 0x00000001017fab08 in crossChildLayout(ASStackLayoutSpecChild const&, ASStackLayoutSpecStyle const&, double, double, double, double, CGSize) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:65
#65 0x00000001017fa944 in ::___ZL43layoutItemsAlongUnconstrainedStackDimensionRNSt3__16vectorI21ASStackLayoutSpecItemNS_9allocatorIS1_EEEERK22ASStackLayoutSpecStylebRK11ASSizeRange6CGSizeb_block_invoke(size_t) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:689
#66 0x00000001017fa6a8 in dispatchApplyIfNeeded(unsigned long, bool, void (unsigned long) block_pointer) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:84
#67 0x00000001017f923c in layoutItemsAlongUnconstrainedStackDimension(std::__1::vector<ASStackLayoutSpecItem, std::__1::allocator >&, ASStackLayoutSpecStyle const&, bool, ASSizeRange const&, CGSize, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:684
#68 0x00000001017f8d08 in ASStackUnpositionedLayout::compute(std::__1::vector<ASStackLayoutSpecChild, std::__1::allocator > const&, ASStackLayoutSpecStyle const&, ASSizeRange const&, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:726
#69 0x00000001017f1ef8 in ::-ASStackLayoutSpec calculateLayoutThatFits: at Pods/Texture/Source/Layout/ASStackLayoutSpec.mm:148
#70 0x00000001017b2004 in ::-[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#71 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#72 0x00000001017fab08 in crossChildLayout(ASStackLayoutSpecChild const&, ASStackLayoutSpecStyle const&, double, double, double, double, CGSize) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:65
#73 0x00000001017fa944 in ::___ZL43layoutItemsAlongUnconstrainedStackDimensionRNSt3__16vectorI21ASStackLayoutSpecItemNS_9allocatorIS1_EEEERK22ASStackLayoutSpecStylebRK11ASSizeRange6CGSizeb_block_invoke(size_t) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:689
#74 0x00000001017fa6a8 in dispatchApplyIfNeeded(unsigned long, bool, void (unsigned long) block_pointer) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:84
#75 0x00000001017f923c in layoutItemsAlongUnconstrainedStackDimension(std::__1::vector<ASStackLayoutSpecItem, std::__1::allocator >&, ASStackLayoutSpecStyle const&, bool, ASSizeRange const&, CGSize, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:684
#76 0x00000001017f8d08 in ASStackUnpositionedLayout::compute(std::__1::vector<ASStackLayoutSpecChild, std::__1::allocator > const&, ASStackLayoutSpecStyle const&, ASSizeRange const&, bool) at Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:726
#77 0x00000001017f1ef8 in ::-ASStackLayoutSpec calculateLayoutThatFits: at Pods/Texture/Source/Layout/ASStackLayoutSpec.mm:148
#78 0x00000001017b2004 in ::-[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#79 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#80 0x000000010179cb84 in ::-[ASInsetLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASInsetLayoutSpec.mm:102
#81 0x00000001017b1e10 in ::-[ASLayoutSpec layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#82 0x00000001017b1d04 in ::-ASLayoutSpec layoutThatFits: at Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#83 0x000000010175c4dc in ::-ASDisplayNode(ASLayoutSpec) calculateLayoutLayoutSpec: at Pods/Texture/Source/ASDisplayNode+LayoutSpec.mm:97
#84 0x0000000101770a04 in ::-ASDisplayNode calculateLayoutThatFits: at Pods/Texture/Source/ASDisplayNode.mm:1114
#85 0x000000010177083c in ::-[ASDisplayNode calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/ASDisplayNode.mm:1096
#86 0x0000000101754974 in ::-[ASDisplayNode(ASLayoutElement) layoutThatFits:parentSize:](ASSizeRange, CGSize) at Pods/Texture/Source/ASDisplayNode+Layout.mm:88
#87 0x000000010175455c in ::-ASDisplayNode(ASLayoutElement) layoutThatFits: at Pods/Texture/Source/ASDisplayNode+Layout.mm:64
#88 0x0000000101741ce0 in ::-[ASDataController _layoutNode:withConstrainedSize:](ASCellNode *, ASSizeRange) at Pods/Texture/Source/Details/ASDataController.mm:195
#89 0x0000000101741b1c in ::__47-[ASDataController _allocateNodesFromElements:]_block_invoke(size_t) at Pods/Texture/Source/Details/ASDataController.mm:175
#90 0x000000010174f31c in ::__ASDispatchApply_block_invoke() at Pods/Texture/Source/Private/ASDispatch.mm:30
#91 0x000000010865d8ac in _dispatch_call_block_and_release ()
#92 0x000000010865ec88 in _dispatch_client_callout ()
#93 0x0000000108670470 in _dispatch_root_queue_drain ()
#94 0x0000000108670b14 in _dispatch_worker_thread2 ()
#95 0x000000018438cf68 in _pthread_wqthread ()
Thread 136#0 0x000000018438fadc in start_wqthread ()
Thread 138#0 0x0000000184468a74 in __workq_kernreturn ()
Thread 147#0 0x0000000184468a74 in __workq_kernreturn ()
Thread 158 Queue : com.qingtui.gcd.default (serial)
#0 0x0000000184467cdc in __psynch_mutexwait ()
#1 0x000000018438a1a4 in _pthread_mutex_firstfit_lock_wait ()
#2 0x000000018438a114 in _pthread_mutex_firstfit_lock_slow$VARIANT$armv81 ()
#3 0x00000001844e962c in std::_1::recursive_mutex::lock() ()
#4 0x00000001016ffa40 in ASDN::Mutex::lock() at Pods/Texture/Source/Details/ASThread.h:169
#5 0x000000010176cb0c in ::-ASDisplayNode lock at Pods/Texture/Source/ASDisplayNode.mm:391
#6 0x000000010186a0e4 in ::-ASTextNode attributedText at Pods/Texture/Source/ASTextNode.mm:454
#7 0x0000000104ca3944 in -[QTChatCellNode cellNodeUpdateDetail:] at /Classes/Chat/ChatVC/TableNodeCell/QTChatCellNode.m:376
#8 0x0000000104cc278c in -[QTChatCellNodeConfig setDetailAttr:] at /Classes/Chat/ChatVC/TableNodeCell/QTChatCellNodeConfig.m:1298
#9 0x0000000104cbd1b0 in -[QTChatCellNodeConfig updateDetail] at /Classes/Chat/ChatVC/TableNodeCell/QTChatCellNodeConfig.m:902
#10 0x0000000104cbf130 in -[QTChatCellNodeConfig notificationAccountUpdate:] at /Classes/Chat/ChatVC/TableNodeCell/QTChatCellNodeConfig.m:1027
#11 0x00000001846752b0 in invoking
()
#12 0x00000001845454e8 in -[NSInvocation invoke] ()
#13 0x00000001845460a4 in -[NSInvocation invokeWithTarget:] ()
#14 0x00000001055deabc in __44-[QTGCDMulticastDelegate forwardInvocation:]_block_invoke at Pods/QTMiddleware/QTMiddleware/Classes/QTEventBus/QTGCDMulticastDelegate.m:343
#15 0x000000010865d8ac in _dispatch_call_block_and_release ()
#16 0x000000010865ec88 in _dispatch_client_callout ()
#17 0x0000000108665bf8 in _dispatch_lane_serial_drain ()
#18 0x0000000108666794 in _dispatch_lane_invoke ()
#19 0x0000000108671b88 in _dispatch_workloop_worker_thread ()
#20 0x000000018438cfa8 in _pthread_wqthread ()
Thread 160#0 0x000000018438fadc in start_wqthread ()
Thread 170#0 0x0000000000000000 in 0x00000000 ()

@businessengine
Copy link

businessengine commented Oct 11, 2019

We face the same issue (we use the branch release/p.37, iOS 13.1). When we comment out [collectionNode waitUntilAllUpdatesAreProcessed]; from our code base (we call this function to wait for the result of collectionNode performBatchAnimated: when loading data into the collection node), leading to another deadlock in ASDataController.
image

@businessengine
Copy link

We used Texture heavily in our apps, with hundred of nodes on a screen. Thus, this issue makes the app crashed after just a few taps. Can anyone please help?

@bkrijgsman
Copy link

Is there already a solution for this issue? We experiencing some deadlocks as well since we build for IOS13

@esam091
Copy link

esam091 commented Nov 15, 2019

I'm getting lots of this issues as well. Is there anything I can do to help?

@businessengine
Copy link

businessengine commented Nov 15, 2019

Try our PR to see if the problem gone #1710 ;-)

@bkrijgsman
Copy link

Unfortunately not :-(

@bkrijgsman
Copy link

I get stuck overhere:

Thread 1 Queue : com.apple.main-thread (serial)
#0	0x00000001a1b94d14 in __psynch_mutexwait ()
#1	0x00000001a1ab9b70 in _pthread_mutex_firstfit_lock_wait ()
#2	0x00000001a1ab9adc in _pthread_mutex_firstfit_lock_slow ()
#3	0x00000001a1c1c030 in std::__1::mutex::lock() ()
#4	0x0000000102243fa8 in ASDN::Mutex::lock() at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/Details/ASThread.h:166
#5	0x00000001023741d8 in std::__1::lock_guard<ASDN::Mutex>::lock_guard(ASDN::Mutex&) at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__mutex_base:104
#6	0x0000000102373e9c in std::__1::lock_guard<ASDN::Mutex>::lock_guard(ASDN::Mutex&) at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__mutex_base:104
#7	0x0000000102373b30 in ::-[ASTextKitContext initWithAttributedString:lineBreakMode:maximumNumberOfLines:exclusionPaths:constrainedSize:](NSAttributedString *, NSLineBreakMode, NSUInteger, NSArray *, CGSize) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/TextKit/ASTextKitContext.mm:44
#8	0x000000010237e130 in ::-[ASTextKitRenderer initWithTextKitAttributes:constrainedSize:](const ASTextKitAttributes &, CGSize) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/TextKit/ASTextKitRenderer.mm:63
#9	0x00000001023abc18 in rendererForAttributes(ASTextKitAttributes, CGSize) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASTextNode.mm:129
#10	0x00000001023ad4bc in ::-[ASTextNode _locked_rendererWithBounds:](CGRect) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASTextNode.mm:357
#11	0x00000001023adad0 in ::-[ASTextNode calculateSizeThatFits:](CGSize) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASTextNode.mm:415
#12	0x00000001022a072c in ::-[ASDisplayNode(ASLayoutSpec) calculateLayoutLayoutSpec:](ASSizeRange) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASDisplayNode+LayoutSpec.mm:45
#13	0x00000001022b4f94 in ::-[ASDisplayNode calculateLayoutThatFits:](ASSizeRange) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASDisplayNode.mm:1114
#14	0x00000001022b4dcc in ::-[ASDisplayNode calculateLayoutThatFits:restrictedToSize:relativeToParentSize:](ASSizeRange, CGSize) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASDisplayNode.mm:1096
#15	0x000000010229ad0c in ::-[ASDisplayNode(ASLayoutInternal) _u_measureNodeWithBoundsIfNecessary:](CGRect) at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASDisplayNode+Layout.mm:371
#16	0x00000001022b4a64 in ::-[ASDisplayNode __layout]() at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASDisplayNode.mm:1048
#17	0x000000010221880c in ::-[_ASDisplayLayer layoutSublayers]() at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/Details/_ASDisplayLayer.mm:99
#18	0x00000001a88863fc in CA::Layer::layout_if_needed(CA::Transaction*) ()
#19	0x00000001a62d341c in -[UIView(Hierarchy) layoutBelowIfNeeded] ()
#20	0x00000001a62d9f60 in +[UIView(Animation) performWithoutAnimation:] ()
#21	0x00000001a602ba84 in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] ()
#22	0x00000001a5ff8704 in -[UITableView _updateVisibleCellsNow:] ()
#23	0x00000001a6015e10 in -[UITableView layoutSubviews] ()
#24	0x000000010235cd14 in ::-[ASTableView layoutSubviews]() at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/ASTableView.mm:777
#25	0x00000001a62e7abc in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#26	0x00000001a1abfaf0 in -[NSObject performSelector:withObject:] ()
#27	0x00000001a88860f4 in -[CALayer layoutSublayers] ()
#28	0x00000001022187dc in ::-[_ASDisplayLayer layoutSublayers]() at /Users/baskrijgsman/appname-ios/Pods/Texture/Source/Details/_ASDisplayLayer.mm:97
#29	0x00000001a88863fc in CA::Layer::layout_if_needed(CA::Transaction*) ()
#30	0x00000001a8899964 in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#31	0x00000001a87dec1c in CA::Context::commit_transaction(CA::Transaction*, double) ()
#32	0x00000001a8809bd8 in CA::Transaction::commit() ()
#33	0x00000001a874333c in CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) ()
#34	0x00000001a8811d30 in display_timer_callback(__CFMachPort*, void*, long, void*) ()
#35	0x00000001a1cfaf34 in __CFMachPortPerform ()
#36	0x00000001a1d2591c in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#37	0x00000001a1d24fe8 in __CFRunLoopDoSource1 ()
#38	0x00000001a1d1fc20 in __CFRunLoopRun ()
#39	0x00000001a1d1f098 in CFRunLoopRunSpecific ()
#40	0x00000001abe89534 in GSEventRunModal ()
#41	0x00000001a5e3f7ac in UIApplicationMain ()
#42	0x000000010099c970 in main at /Users/baskrijgsman/appname-ios/AppName/AppNameDelegate.swift:27
#43	0x00000001a1b9ef30 in start ()

@esam091
Copy link

esam091 commented Nov 20, 2019

Try our PR to see if the problem gone #1710 ;-)

Also not working for me either :(

@rahul-malik
Copy link
Contributor

rahul-malik commented Nov 26, 2019

Investigation into deadlocks with iOS13 text rendering

Attn: @businessengine @esam091 @bkrijgsman @CoderXL

We're looking into this at Pinterest since we're also hitting the issue. A couple things have popped out in our investigation:

Possibly unnecessary global mutex

  • The usage of a global mutex for all text kit renderering seems to be unnecessary at this time and quite possibly has been for a while.
    Have you tried enabling the ASExperimentalRemoveTextKitInitialisingLock experiment? ASTextKitContext shares a single global mutex which we believe is contributing to deadlocks.

I wrote a simple unit test to make sure that allocating thousands of ASTextKitContent objects did not deadlock when this mutex was disabled. This test gives us decent confidence that the root cause of the global mutex (written in 2015) might have been resolved a while ago.

- (void)testTextKitComponentsCanBeAllocatedConcurrently
{
  ASConfiguration *config = [ASConfiguration new];
  config.experimentalFeatures = ASExperimentalRemoveTextKitInitialisingLock;
  [ASConfigurationManager test_resetWithConfiguration:config];

  NSAttributedString *attributedString =
  [[NSAttributedString alloc]
   initWithString:@"90's cray photo booth tote bag bespoke Carles. Plaid wayfarers Odd Future master cleanse tattooed four dollar toast small batch kale chips leggings meh photo booth occupy irony.  " attributes:@{}];
  dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);

  for (NSUInteger i = 0; i < 5000; i++) {
    XCTestExpectation *expectation = [self expectationWithDescription:@"Allocate textkit content"];

    dispatch_async(queue, ^{
      ASTextKitContext *context = [[ASTextKitContext alloc]
      initWithAttributedString:attributedString
                  tintColor:nil
              lineBreakMode:NSLineBreakByWordWrapping
       maximumNumberOfLines:3
             exclusionPaths:nil
                                        constrainedSize:CGSizeMake(100, 100)];
      XCTAssert(context != nil);
      [expectation fulfill];
    });
  }

  [self waitForExpectationsWithTimeout:60 handler:nil];
}

Please test out that experiment and let us know if you're still able to reproduce the issue

Deadlock in background layout calculation

  • ASDataController seems to be calculating layouts in the background. For layout calculation of text nodes, NSTextStorage appears to be blocked waiting for the main thread when it's attributed string is set. The Data Controller is waiting for the nodes to concurrently calculate layout and blocks until finished. If those layout calculations require work to be performed on main then we have a deadlock.

For ASTextNode, the text kit renderer abstraction has a class called ASTextKitContext which creates and owns the underlying NSTextStorage / NSLayoutManager instances for a given text node. When the attributed string is set on NSTextStorage it appears to post notifications for NSTextStorageWillProcessEditingNotification and NSTextStorageDidProcessEditingNotification on the main thread and blocks the current background thread until finished.

This leads to a few problems

  • Deadlock since the data controller is waiting for cell layout calculations to finish (-[ASDataController updateWithChangeSet:])
  • Text nodes are waiting for +[NSOperationQueue mainQueue] to process a notification from the background layout (see -[NSOperation waitUntilFinished])
Thread 135 Queue : com.apple.root.user-initiated-qos (concurrent)
#0	0x0000000184467c8c in __psynch_cvwait ()
#1	0x00000001843894e4 in _pthread_cond_wait$VARIANT$armv81 ()
#2	0x00000001849b22e4 in -[NSOperation waitUntilFinished] ()
#3	0x000000018494e8c8 in -[__NSObserver _doit:] ()
#4	0x00000001845ca9ac in CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER ()
#5	0x00000001845ca9f4 in ___CFXRegistrationPost1_block_invoke ()
#6	0x00000001845c9d54 in _CFXRegistrationPost1 ()
#7	0x00000001845c9a20 in ___CFXNotificationPost_block_invoke ()
#8	0x0000000184545d38 in -[_CFXNotificationRegistrar find:object:observer:enumerator:] ()
#9	0x00000001845c9370 in _CFXNotificationPost ()
#10	0x0000000184925cf8 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#11	0x0000000187ba2b44 in -[NSTextStorage processEditing] ()
#12	0x0000000187ba337c in -[NSTextStorage edited:range:changeInLength:] ()
#13	0x0000000184979d60 in -[NSConcreteMutableAttributedString replaceCharactersInRange:withAttributedString:] ()
#14	0x0000000187c241ac in __71-[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:]_block_invoke ()
#15	0x0000000187c23ddc in __NSConcreteTextStorageLockedForwarding ()
#16	0x0000000187ba90e4 in -[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:] ()
#17	0x000000010182fc74 in ::-[ASTextKitContext initWithAttributedString:lineBreakMode:maximumNumberOfLines:exclusionPaths:constrainedSize:]
  • Unbounded growth in threads since every text rendering action is blocked either from the deadlock or mutex which results in new threads created to continue text rendering calculations.

We're currently discussing the right fix but I believe this is what we're seeing with the adoption of iOS 13.

Hope this helps!

@rcancro
Copy link
Contributor

rcancro commented Nov 26, 2019

As @rahul-malik mentioned, when we looked into this it appeared that NSTextStorage was calling out to another thread to run an operation and then sitting there waiting for it:

#2	0x00000001849b22e4 in -[NSOperation waitUntilFinished] ()
#3	0x000000018494e8c8 in -[__NSObserver _doit:] ()
#4	0x00000001845ca9ac in CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER ()
#5	0x00000001845ca9f4 in ___CFXRegistrationPost1_block_invoke ()
#6	0x00000001845c9d54 in _CFXRegistrationPost1 ()
#7	0x00000001845c9a20 in ___CFXNotificationPost_block_invoke ()
#8	0x0000000184545d38 in -[_CFXNotificationRegistrar find:object:observer:enumerator:] ()
#9	0x00000001845c9370 in _CFXNotificationPost ()
#10	0x0000000184925cf8 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()

From the above call stack, it looks like _doit: is the one that actually kicks off the operation. The next method, waitUntilFinished, is where we start synchronously waiting for it to finish. I swizzled _doit: to try to get a better look at __NSObserver and see what it is doing. From a header dump, I could see that __NSObserver has a queue member. Inspecting that queue prints outs:

Printing description of _self->queue:
<NSOperationQueue: 0x109b497e0>{name = 'NSOperationQueue Main Queue'}

This seemed to back up our theory that this operation was being queued on the main thread while the main thread was synchronously waiting for the posting thread to finish layout. We were also able to verify that the notification that is being handled is either NSTextStorageWillProcessEditingNotification or NSTextStorageDidProcessEditingNotification. I don't know if this notification has started jumping to main in iOS13, or if the likelihood of it jumping to main has increased, but we are seeing deadlocks more in iOS13 than other versions.

The long term fix for this type of deadlock is probably to stop relying on ASMainSerialQueue -- that is stop synchronously waiting forever on main for anything. You can never know when the things you are waiting for will need to synchronously wait for something to run on main!

Our proposed quick fix for this is kind of gross, but so far seems to be working. Basically we are swizzling __NSObserver's _doit: method and dispatching asynchronously to main any time the notification that we are "doing" is either NSTextStorageWillProcessEditingNotification or NSTextStorageDidProcessEditingNotification. It looks something like this:

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // we are swizzling the __NSObserver class (you may want to obfuscate this string)
    Class class = [NSClassFromString(@"__NSObserver") class];

    // we are swizzling the doit: method (you may want to obfuscate this string)
    SEL originalSelector = NSSelectorFromString(@"_doit:");
    SEL swizzledSelector = NSSelectorFromString(@"swizzled_doit:");

    Method origMethod = class_getInstanceMethod(class, originalSelector);
    
    // Create a new implementation via a block
    IMP impl = imp_implementationWithBlock(^(id _self, id arg) {
        NSNotification *notification = (NSNotification *)arg;
        // make sure arg is a notification, then check to see if it is NSTextStorageDidProcessEditingNotification or NSTextStorageDidProcessEditingNotification
        if ([notification isKindOfClass:[NSNotification class]] && notification &&
            ([[notification name] isEqualToString:NSTextStorageDidProcessEditingNotification] || [[notification name] isEqualToString:NSTextStorageWillProcessEditingNotification])) {
            // This is the notification we are looking for. _doit: will jump to the main thread and wait until the operation is attended to.
            // Instead, let's dispatch doit: asynchrously to the main thread. that will allow layout to continue so main will stop blocking
            // and then _doit: will eventually run on main.
             dispatch_async(dispatch_get_main_queue(),^{
                ((void (*)(id, SEL, NSNotification *))objc_msgSend)(_self, swizzledSelector, arg);
            });
        } else {
            // This isn't the notification we are looking for. Proceed without any dispatching to main
            ((void (*)(id, SEL, NSNotification *))objc_msgSend)(_self, swizzledSelector, arg);
        }
    });
        
    // add the new method to the class
    if (class_addMethod(class, swizzledSelector, impl, method_getTypeEncoding(origMethod))) {
        
        Method newMethod = class_getInstanceMethod(class, swizzledSelector);
        // If original doesn't implement the method we want to swizzle, create it.
        if (class_addMethod(class, originalSelector, method_getImplementation(newMethod), method_getTypeEncoding(origMethod))) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(origMethod), method_getTypeEncoding(newMethod));
        } else {
            method_exchangeImplementations(origMethod, newMethod);
        }
    }
});

My biggest concern about this is that UIKit must be dispatching to main and waiting for some reason. Whatever that reason may be, we are basically ignoring it with this change. But UIKit probably doesn't expect main to be synchronously waiting for anything, and layout on a background thread is so non-UIKit that perhaps this change will end up being innocuous.

@nguyenhuy
Copy link
Member

nguyenhuy commented Nov 26, 2019

Great findings on the (new?) behavior of NSTextStorage you all.

I would like to chime in a bit to provide an insight on the default behavior of ASDataController, hopefully without distracting you from the discussion for the right fix. By default ASDataController does not block main thread while processing a batch update on background thread(s), unless the number of new cell nodes is 0 or 1 (although I think we can get rid of this caveat).

Clients can change the default behavior by either setting cell layout mode to ASCellLayoutModeAlwaysSync, or calling -waitUntilAllUpdatesAreProcessed on the collection/table node.

It's true that if ASDataController blocks main and one of the background threads (that is responsible for processing the batch update) tries to dispatch sync back to main, we’ll hit a deadlock. This means -waitUntilAllUpdatesAreProcessed is no longer a safe API. So I agree with @rcancro that the long term fix is probably to stop synchronously waiting forever on main, essentially getting rid of -waitUntilAllUpdatesAreProcessed and perhaps ASMainSerialQueue.

Edit: clarify the default behavior of ASDataController and my thought on the long term fix.

@esam091
Copy link

esam091 commented Dec 2, 2019

Thanks for the clarification @rahul-malik, I'm gonna try some solutions based on what you explained.

@bkrijgsman
Copy link

@esam091 Have you find any solution yet?

@esam091
Copy link

esam091 commented Feb 2, 2020

We ended up replacing ASTextNode with ASTextNode2 on screens that have the problem. The problem isn't totally gone but significantly reduced for now.

@bkrijgsman
Copy link

Amazing that worked really well. We couldn't trigger a freeze ourselves anymore.

@nguyenhuy
Copy link
Member

@esam091 Could you please verify if ASTextNode2 doesn't have this issue and the issue isn't totally gone because you still have ASTextNode somewhere else in your app? Or that ASTextNode2 still hits this deadlock occasionally?

I believe the former is the case since ASTextNode uses TextKit which has a new behavior on iOS 13 that causes NSTextStorage to deadlock, and ASTextNode2 doesn't use TextKit but CoreText directly.

@esam091
Copy link

esam091 commented Feb 21, 2020

We do still have a lot of ASTextNodes, and only change them to ASTextNode2 on view controllers with lots of freezes. After talking to my coworkers, the freezes don't happen on those screens anymore, it was somewhere else. Maybe it is caused by something unrelated, we're not so sure because it happens so infrequently.

@businessengine
Copy link

Thanks for all the comments, folks. We have tried to replace ASTextNode by ASTextNode2 however the ASTextNode2 seems having performance issues, the render is noticeable slow comparing to ASTextNode. Is that expected @nguyenhuy?

@steewsc
Copy link

steewsc commented Apr 1, 2020

Hi,
I think(hope :) ) I'm facing the same issue, just wanted confirm.
Crash happened a few times to our QA team, randomly, (I can not reproduce it) but always in Messaging part of our app, either in InboxTVC or ThreadTVC (90% ASTextnodes)
In all cases resulting the app to freeze before being terminated:

OS Version: iPhone OS 13.3.1 (17D50)

Exception Type: EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Termination Description: SPRINGBOARD, scene-update watchdog transgression: application<com.cmp.MyApp>:14108 exhausted real (wall clock) time allowance of 10.00 seconds | ProcessVisibility: Foreground | ProcessState: Running | WatchdogEvent: scene-update | WatchdogVisibility: Background | WatchdogCPUStatistics: ( | "Elapsed total CPU time (seconds): 17.960 (user 17.960, system 0.000), 10% CPU", | "Elapsed application CPU time (seconds): 0.448, 0% CPU" | )
Triggered by Thread: 0

With stacktrace:

Dispatch queue: com.apple.main-thread (0)
#0 (null) in __psynch_mutexwait ()
#1 (null) in _pthread_mutex_firstfit_lock_wait ()
#2 (null) in _pthread_mutex_firstfit_lock_slow$VARIANT$armv81 ()
#3 (null) in std::__1::mutex::lock+ 255152 () ()
#4 0x0000000103841c3c in -[ASTextKitContext initWithAttributedString:lineBreakMode:maximumNumberOfLines:exclusionPaths:constrainedSize:] at /Pods/Texture/Source/TextKit/ASTextKitContext.mm:46
#5 0x0000000103846a70 in -[ASTextKitRenderer initWithTextKitAttributes:constrainedSize:] at /Pods/Texture/Source/TextKit/ASTextKitRenderer.mm:63
#6 (null) in rendererForAttributes(ASTextKitAttributes, CGSize) ()
#7 0x000000010385e640 in -[ASTextNode _locked_rendererWithBounds:] at /Pods/Texture/Source/ASTextNode.mm:357
#8 (null) in -[ASTextNode calculateSizeThatFits:] ()
#9 0x00000001037e479c in -[ASDisplayNode(ASLayoutSpec) calculateLayoutLayoutSpec:] at /Pods/Texture/Source/ASDisplayNode+LayoutSpec.mm:47
#10 (null) in -[ASDisplayNode calculateLayoutThatFits:] ()
#11 0x00000001037efb48 in -[ASDisplayNode calculateLayoutThatFits:restrictedToSize:relativeToParentSize:] at /Pods/Texture/Source/ASDisplayNode.mm:1106
#12 (null) in -[ASDisplayNode(ASLayoutElement) layoutThatFits:parentSize:] ()
#13 (null) in -[ASRelativeLayoutSpec calculateLayoutThatFits:] ()
#14 0x000000010380dbb4 in -[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:] at /Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#15 (null) in -[ASLayoutSpec layoutThatFits:parentSize:] ()
#16 (null) in crossChildLayout(ASStackLayoutSpecChild const&, ASStackLayoutSpecStyle const&, double, double, double, double, CGSize) ()
#17 (null) in invocation function for block in layoutItemsAlongUnconstrainedStackDimension(std::__1::vector<ASStackLayoutSpecItem, std::__1::allocator >&, ASStackLayoutSpecStyle const&, bool, ASSizeRange const&, CGSize, bool) ()
#18 0x000000010382d0b4 in dispatchApplyIfNeeded(unsigned long, bool, void (unsigned long) block_pointer) at /Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:83
#19 0x000000010382c304 in ASStackUnpositionedLayout::compute(std::__1::vector<ASStackLayoutSpecChild, std::__1::allocator > const&, ASStackLayoutSpecStyle const&, ASSizeRange const&, bool) at /Pods/Texture/Source/Private/Layout/ASStackUnpositionedLayout.mm:734
#20 0x000000010382ac64 in -[ASStackLayoutSpec calculateLayoutThatFits:] at /Pods/Texture/Source/Layout/ASStackLayoutSpec.mm:149
#21 0x000000010380dbb4 in -[ASLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:] at /Pods/Texture/Source/Layout/ASLayoutSpec.mm:80
#22 (null) in -[ASLayoutSpec layoutThatFits:parentSize:] ()
#23 (null) in -[ASInsetLayoutSpec calculateLayoutThatFits:restrictedToSize:relativeToParentSize:] ()
#24 (null) in -[ASLayoutSpec layoutThatFits:parentSize:] ()
#25 (null) in -[ASDisplayNode(ASLayoutSpec) calculateLayoutLayoutSpec:] ()
#26 (null) in -[ASDisplayNode calculateLayoutThatFits:] ()
#27 0x00000001037efb48 in -[ASDisplayNode calculateLayoutThatFits:restrictedToSize:relativeToParentSize:] at /Pods/Texture/Source/ASDisplayNode.mm:1106
#28 (null) in -[ASDisplayNode(ASLayoutElement) layoutThatFits:parentSize:] ()
#29 (null) in -[ASTableView didLayoutSubviewsOfTableViewCell:] ()
#30 0x0000000103832e30 in -[_ASTableViewCell layoutSubviews] at /Pods/Texture/Source/ASTableView.mm:89
#31 (null) in -[UIView+ 15307132 (CALayerDelegate) layoutSublayersOfLayer:] ()
#32 (null) in -[CALayer layoutSublayers] ()
#33 (null) in CA::Layer::layout_if_needed+ 1406012 (CA::Transaction*) ()
#34 (null) in -[UIView+ 15225904 (Hierarchy) layoutBelowIfNeeded] ()
#35 (null) in +[UIView+ 15252500 (Animation) performWithoutAnimation:] ()
#36 (null) in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] ()
#37 (null) in -[UITableView _createPreparedCellForGlobalRow:willDisplay:] ()
#38 (null) in -[_UITableViewUpdateSupport+ 12651728 (Private) _setupAnimationsForNewlyInsertedCells] ()
#39 (null) in -[_UITableViewUpdateSupport _setupAnimations] ()
#40 (null) in -[UITableView _updateWithItems:updateSupport:] ()
#41 (null) in -[UITableView _endCellAnimationsWithContext:] ()
#42 (null) in -[UITableView endUpdatesWithContext:] ()
#43 0x000000010383a378 in -[ASTableView rangeController:updateWithChangeSet:updates:] at /Pods/Texture/Source/ASTableView.mm:1655
#44 0x0000000103826700 in -[ASRangeController dataController:updateWithChangeSet:updates:] at /Pods/Texture/Source/Details/ASRangeController.mm:517
#45 0x00000001037da818 in __40-[ASDataController updateWithChangeSet:]_block_invoke_2.193 at /Pods/Texture/Source/Details/ASDataController.mm:665
#46 0x0000000103811558 in __30-[ASMainSerialQueue runBlocks]_block_invoke at /Pods/Texture/Source/Details/ASMainSerialQueue.mm:68
#47 (null) in _dispatch_call_block_and_release ()
#48 (null) in _dispatch_client_callout ()
#49 (null) in _dispatch_main_queue_callback_4CF$VARIANT$armv81 ()
#50 (null) in CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE ()
#51 (null) in __CFRunLoopRun ()
#52 (null) in CFRunLoopRunSpecific ()
#53 (null) in GSEventRunModal ()
#54 (null) in UIApplicationMain ()
#55 0x000000010297b018 in main at /MyApp/AppDelegate.swift:23
#56 (null) in start ()

@esam091
Copy link

esam091 commented Apr 8, 2020

I've tried removing locks here and here, and the deadlocks seem to be gone just as @rahul-malik said #1690 (comment). I'm not sure whether this is a safe solution though 😅.

Maybe @steewsc and @bkrijgsman want to give it a try?

@steewsc
Copy link

steewsc commented Apr 14, 2020

@esam091 thank you,
but I've already replaced all ASTextNodes and ASButtonNodes with ASTextNode2 and there are no crashes so far.

@savan0714
Copy link

Hi @esam091 @businessengine

Any luck with the fix?
I am still getting this in iOS 14 and above.

I have tried removing the locks suggested in this comment #1690 (comment)

Above removal of lock removed the issue in iOS 13.
But it started occurring again in iOS 14 and above.

Please help this if you have any solutions.

@rcancro
Copy link
Contributor

rcancro commented May 10, 2021

We also saw this come back in iOS14. We were able to get around it by swizzling farther up the stack in iOS13. Instead of swizzling _doit: we swizzled postNotificationName:object:userInfo:. Looking at the code above, I think you'll want to make these changes (I didn't test this code 🤞 ):

    // we are swizzling the NSNotificationCenter class
    Class class = [NSClassFromString(@"NSNotificationCenter") class];

    // we are swizzling the postNotificationName:object:userInfo: method
    SEL postSelector = NSSelectorFromString(@"postNotificationName:object:userInfo:");
    SEL piPostSelector = NSSelectorFromString(@"swizzled_postNotificationName:object:userInfo:");

Once this is in you can remove the _doit: swizzle.

@JohnEstropia
Copy link

iOS 15 now but this issue is still happening with ASTextNode. Did anyone resolve it with a less-intrusive approach than swizzling -[__NSObserver _doit:]? We've considered using ASTextNode2 instead, but we find its rendering and layout is quite unstable.

@JohnEstropia
Copy link

JohnEstropia commented Dec 7, 2021

Just a word of caution to anyone using the swizzling solutions above:
I've found that it messes up the delegate events in some UIKit controls. For example in UISearchBar, the UISearchTokens disappear because internally the UISearchTextField.tokens do not get retained in time. The result is that by the time UISearchBarDelegate's didChangeText is called UISearchTextField.tokens will always be empty, preventing any reliable state management.

@JohnEstropia
Copy link

FYI, I think I know why UIKit runs NSTextStorage processing synchronously. It turns out NSTextStorage is a class-cluster, and our swizzling workarounds in this thread should only be used on "NSConcreteTextStorage". Other types such as _UICascadingTextStorage (used by UISearchBar tokens for example) seem to do recursive calculations that would cause range issues (including out-of-range exceptions) if ran asynchronously.

@Mammadbayli
Copy link

Hello, Have we reached a consensus on how to fix this issue? I am currently struggling with these crashes. :/

@JohnEstropia
Copy link

JohnEstropia commented Apr 24, 2022

Applying the swizzling suggestions in this thread AND filtering the swizzled method only for NSConcreteTextStorage senders should help you. Below is what I use and it's pretty stable so far. If you find exceptions that should be added aside from NSConcreteTextStorage, please do share.

@implementation ASTextNode (App)

+ (void)load {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        Class class = [NSNotificationCenter class];
        SEL originalSelector = @selector(postNotificationName:object:userInfo:);
        SEL swizzledSelector = NSSelectorFromString(@"swizzled_postNotificationName:object:userInfo:");

        Method origMethod = class_getInstanceMethod(class, originalSelector);
        
        IMP impl = imp_implementationWithBlock(^(id _self, id name, id object, id userInfo) {
            
            if ([name isKindOfClass:[NSString class]]
                && ([name isEqualToString:NSTextStorageDidProcessEditingNotification]
                    || [name isEqualToString:NSTextStorageWillProcessEditingNotification])
                && [NSStringFromClass([object class]) isEqualToString:@"NSConcreteTextStorage"]) {
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    
                    ((void (*)(id, SEL, NSString *, id, NSDictionary *))objc_msgSend)(_self, swizzledSelector, name, object, userInfo);
                });
            }
            else {
                
                ((void (*)(id, SEL,NSString *, id, NSDictionary *))objc_msgSend)(_self, swizzledSelector, name, object, userInfo);
            }
        });
            
        if (class_addMethod(class, swizzledSelector, impl, method_getTypeEncoding(origMethod))) {
            
            Method newMethod = class_getInstanceMethod(class, swizzledSelector);
            if (class_addMethod(class, originalSelector, method_getImplementation(newMethod), method_getTypeEncoding(origMethod))) {
                
                class_replaceMethod(class, swizzledSelector, method_getImplementation(origMethod), method_getTypeEncoding(newMethod));
            }
            else {
                
                method_exchangeImplementations(origMethod, newMethod);
            }
        }
    });
}

@end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests