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

[Text][Crash] RCTText setTextStorage crashes #2001

Closed
ide opened this issue Jul 15, 2015 · 24 comments
Closed

[Text][Crash] RCTText setTextStorage crashes #2001

ide opened this issue Jul 15, 2015 · 24 comments
Labels
Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@ide
Copy link
Contributor

ide commented Jul 15, 2015

This is on master after the Tuesday sync. Perhaps the text scaling diff revealed or introduced this bug. I don't have a repro case (seems to happen on reload) but this is the stack trace:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib                 0x000000010b3679c0 objc_release + 16
1   app                             0x000000010a503f54 -[RCTText setTextStorage:] + 68 (RCTText.m:72)
2   app                             0x000000010a4f3eca __59-[RCTShadowText processUpdatedProperties:parentProperties:]_block_invoke + 154 (RCTShadowText.m:91)
3   app                             0x000000010a51ae9a __75-[RCTUIManager _amendPendingUIBlocksWithStylePropagationUpdateForRootView:]_block_invoke + 410 (RCTUIManager.m:639)
4   app                             0x000000010a517333 __27-[RCTUIManager addUIBlock:]_block_invoke + 131 (RCTUIManager.m:466)
5   app                             0x000000010a524d5d __29-[RCTUIManager flushUIBlocks]_block_invoke + 365 (RCTUIManager.m:1336)
6   libdispatch.dylib               0x000000010e780f16 _dispatch_call_block_and_release + 12
7   libdispatch.dylib               0x000000010e79b964 _dispatch_client_callout + 8
8   libdispatch.dylib               0x000000010e786a59 _dispatch_main_queue_callback_4CF + 704
9   com.apple.CoreFoundation        0x000000010ba6d1f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
10  com.apple.CoreFoundation        0x000000010ba2edcb __CFRunLoopRun + 2043
11  com.apple.CoreFoundation        0x000000010ba2e366 CFRunLoopRunSpecific + 470
12  com.apple.GraphicsServices      0x00000001115eca3e GSEventRunModal + 161
13  com.apple.UIKit                 0x000000010cfd88c0 UIApplicationMain + 1282
14  app                             0x000000010a4335cf main + 111 (main.m:9)
15  libdyld.dylib                   0x000000010e7cb145 start + 1

With zombies I get [NSConcreteTextStorage release]: message sent to deallocated instance 0x7f99ff5bddf0. Maybe a bug in Core Text or iOS 8.4?

@admmasters
Copy link
Contributor

Hmmm - is this definitely new? I'm fairly sure I've seen similar stack trace errors in previous releases.

@ide
Copy link
Contributor Author

ide commented Jul 15, 2015

Pretty sure this is new or the old bug is back.

@sahrens
Copy link
Contributor

sahrens commented Jul 15, 2015

We reverted dynamic text size stuff internally, but for different reasons...

@ide
Copy link
Contributor Author

ide commented Jul 15, 2015

With the Jul 15 sync that includes the revert I'm not seeing the crash anymore.

@MattFoley
Copy link

@ide @brentvatne I'm still seeing this occasionally on reload, same result with zombies:
*** -[NSConcreteTextStorage release]: message sent to deallocated instance 0x7fb938ef9350

@ide
Copy link
Contributor Author

ide commented Sep 2, 2015

I started seeing this again too, although I haven't encountered it yet after pulling in yesterday's sync.

@MattFoley
Copy link

Oh, cool, we're about just on 0.11-rc, hopefully it's contained to just refreshes :)

@MattFoley
Copy link

I should actually ask, have you seen this manifest anywhere other than during a refresh?

@ide
Copy link
Contributor Author

ide commented Sep 2, 2015

Just during reloading so far.

@ide
Copy link
Contributor Author

ide commented Sep 2, 2015

I hit it again :/

@ide ide reopened this Sep 2, 2015
@sahrens
Copy link
Contributor

sahrens commented Sep 3, 2015

Can you take a look at this, Alex?

@ide
Copy link
Contributor Author

ide commented Sep 4, 2015

Someone was telling me that CoreText may not actually be threadsafe in a couple cases. That is you can use it off the main thread but it might not support concurrency. In this case the crash looks related to deallocation so maybe the module is getting dealloc'd from a thread/queue other than its own?

@ide
Copy link
Contributor Author

ide commented Sep 11, 2015

Couple more text-related crashes (this time from iOS 9):

Thread : Crashed: Thread
0  libobjc.A.dylib                0x000000019ab99bd0 objc_msgSend + 16
1  CoreText                       0x0000000186a94aa0 TBaseFont::~TBaseFont() + 372
2  CoreText                       0x0000000186b22f50 TSplicedFont::~TSplicedFont() + 388
3  CoreText                       0x0000000186b22f94 TSplicedFont::~TSplicedFont() + 12
4  CoreText                       0x0000000186a6c648 TReferenced::Adopt(MReferenceCounted const*) + 60
5  CoreText                       0x0000000186a6c5e8 TDescriptor::~TDescriptor() + 56
6  CoreFoundation                 0x0000000185e78da4 CFRelease + 256
7  CoreFoundation                 0x0000000185f15a54 __CFArrayReleaseValues + 264
8  CoreFoundation                 0x0000000185e78da4 CFRelease + 256
9  CoreText                       0x0000000186a82e2c TSplicedFontStash::DestroyCache(void*) + 32
10 CoreText                       0x0000000186a82ad0 DestroyTable(void*) + 48
11 libsystem_pthread.dylib        0x000000019b5961e8 <redacted> + 584
12 libsystem_pthread.dylib        0x000000019b595d60 <redacted> + 136
13 libsystem_pthread.dylib        0x000000019b595544 _pthread_wqthread + 1294
14 libsystem_pthread.dylib        0x000000019b595028 start_wqthread + 4
Thread : Crashed: Thread
0  libobjc.A.dylib                0x000000019924dbd0 objc_msgSend + 16
1  CoreText                       0x00000001853b478c TDescriptor::~TDescriptor() + 68
2  CoreFoundation                 0x00000001847c1884 CFRelease + 256
3  CoreFoundation                 0x000000018485e568 __CFArrayReleaseValues + 224
4  CoreFoundation                 0x00000001847c1884 CFRelease + 256
5  CoreText                       0x000000018546b180 TSplicedFont::~TSplicedFont() + 360
6  CoreText                       0x000000018546b1e0 TSplicedFont::~TSplicedFont() + 12
7  CoreText                       0x00000001853b47e0 TReferenced::Adopt(MReferenceCounted const*) + 60
8  CoreText                       0x00000001853b4780 TDescriptor::~TDescriptor() + 56
9  CoreFoundation                 0x00000001847c1884 CFRelease + 256
10 CoreFoundation                 0x000000018485e590 __CFArrayReleaseValues + 264
11 CoreFoundation                 0x00000001847c1884 CFRelease + 256
12 CoreText                       0x00000001853cb0d0 TSplicedFontStash::DestroyCache(void*) + 32
13 CoreText                       0x00000001853cad74 DestroyTable(void*) + 48
14 libsystem_pthread.dylib        0x0000000199c6e1e8 _pthread_tsd_cleanup + 584
15 libsystem_pthread.dylib        0x0000000199c6dd60 _pthread_exit + 136
16 libsystem_pthread.dylib        0x0000000199c6d544 pthread_mutex_lock + 1294
17 libsystem_pthread.dylib        0x0000000199c6d028 start_wqthread + 4

@sahrens
Copy link
Contributor

sahrens commented Sep 11, 2015

I saw this a bunch the other day when reloading the bridge, profiling,
attaching the debugger, etc. @tadeuzagallo or @nicklockwood?
On Sep 10, 2015 10:31 PM, "James Ide" notifications@github.com wrote:

Couple more text-related crashes (this time from iOS 9):

Thread : Crashed: Thread
0 libobjc.A.dylib 0x000000019ab99bd0 objc_msgSend + 16
1 CoreText 0x0000000186a94aa0 TBaseFont::~TBaseFont() + 372
2 CoreText 0x0000000186b22f50 TSplicedFont::~TSplicedFont() + 388
3 CoreText 0x0000000186b22f94 TSplicedFont::~TSplicedFont() + 12
4 CoreText 0x0000000186a6c648 TReferenced::Adopt(MReferenceCounted const_) + 60
5 CoreText 0x0000000186a6c5e8 TDescriptor::~TDescriptor() + 56
6 CoreFoundation 0x0000000185e78da4 CFRelease + 256
7 CoreFoundation 0x0000000185f15a54 _CFArrayReleaseValues + 264
8 CoreFoundation 0x0000000185e78da4 CFRelease + 256
9 CoreText 0x0000000186a82e2c TSplicedFontStash::DestroyCache(void
) + 32
10 CoreText 0x0000000186a82ad0 DestroyTable(void*) + 48
11 libsystem_pthread.dylib 0x000000019b5961e8 + 584
12 libsystem_pthread.dylib 0x000000019b595d60 + 136
13 libsystem_pthread.dylib 0x000000019b595544 _pthread_wqthread + 1294
14 libsystem_pthread.dylib 0x000000019b595028 start_wqthread + 4

Thread : Crashed: Thread
0 libobjc.A.dylib 0x000000019924dbd0 objc_msgSend + 16
1 CoreText 0x00000001853b478c TDescriptor::~TDescriptor() + 68
2 CoreFoundation 0x00000001847c1884 CFRelease + 256
3 CoreFoundation 0x000000018485e568 _CFArrayReleaseValues + 224
4 CoreFoundation 0x00000001847c1884 CFRelease + 256
5 CoreText 0x000000018546b180 TSplicedFont::~TSplicedFont() + 360
6 CoreText 0x000000018546b1e0 TSplicedFont::~TSplicedFont() + 12
7 CoreText 0x00000001853b47e0 TReferenced::Adopt(MReferenceCounted const
) + 60
8 CoreText 0x00000001853b4780 TDescriptor::~TDescriptor() + 56
9 CoreFoundation 0x00000001847c1884 CFRelease + 256
10 CoreFoundation 0x000000018485e590 _CFArrayReleaseValues + 264
11 CoreFoundation 0x00000001847c1884 CFRelease + 256
12 CoreText 0x00000001853cb0d0 TSplicedFontStash::DestroyCache(void
) + 32
13 CoreText 0x00000001853cad74 DestroyTable(void*) + 48
14 libsystem_pthread.dylib 0x0000000199c6e1e8 _pthread_tsd_cleanup + 584
15 libsystem_pthread.dylib 0x0000000199c6dd60 _pthread_exit + 136
16 libsystem_pthread.dylib 0x0000000199c6d544 pthread_mutex_lock + 1294
17 libsystem_pthread.dylib 0x0000000199c6d028 start_wqthread + 4


Reply to this email directly or view it on GitHub
#2001 (comment)
.

@mkonicek
Copy link
Contributor

How often does this happen? I just talked to @tadeuzagallo and he says it's a race condition when ARC releases the memory. He saw it happen very rarely when reloading JS so it's fairly hard to repro, we're not sure about the right fix yet.

@finalquest
Copy link

I hit this issue only when running the test suite. No mather how I run it, one component will always crash, not always the same.
The app itself is working fine until now

@javache
Copy link
Member

javache commented Sep 24, 2015

@finalquest Does that still happen when you run your tests against the latest version from master? 9b1f6c9 has made this error disappear for us when running tests.

@finalquest
Copy link

I will try to use master and report to this thread

@ide
Copy link
Contributor Author

ide commented Sep 29, 2015

Here are some more detailed stack traces, though they don't really point to the issue. The environment is master (0.13-dev) iPhone 6 simulator, iOS 9.0, Xcode 7, ASan enabled. Can also repro with ASan disabled and with the Chrome debugger.

I find it strange that an RCTText object (that I have a strong reference to) has a strong reference to an NSTextStorage object that is deallocated.


-[NSConcreteTextStorage release]: message sent to deallocated instance 0x612000518440

thread #1: tid = 0xafbc79, 0x0000000111a76eaf CoreFoundation`___forwarding___ + 767, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x0000000111a76eaf CoreFoundation`___forwarding___ + 767
frame #1: 0x0000000111a76b28 CoreFoundation`__forwarding_prep_0___ + 120
frame #2: 0x000000010de55759 App`-[RCTText setTextStorage:](self=0x000061400008b640, _cmd="setTextStorage:", textStorage=0x00006120007cf540) + 377 at RCTText.m:78
frame #3: 0x000000010de29338 App`__59-[RCTShadowText processUpdatedProperties:parentProperties:]_block_invoke(.block_descriptor=<unavailable>, viewRegistry=0x0000602000016830) + 712 at RCTShadowText.m:91
frame #4: 0x000000010de90405 App`__75-[RCTUIManager _amendPendingUIBlocksWithStylePropagationUpdateForRootView:]_block_invoke(.block_descriptor=<unavailable>, uiManager=0x000060c00013ef40, viewRegistry=0x0000602000016830) + 1253 at RCTUIManager.m:569
frame #5: 0x000000010de88843 App`__27-[RCTUIManager addUIBlock:]_block_invoke(.block_descriptor=<unavailable>) + 707 at RCTUIManager.m:423
frame #6: 0x000000010de9f356 App`__29-[RCTUIManager flushUIBlocks]_block_invoke(.block_descriptor=<unavailable>) + 1238 at RCTUIManager.m:883
frame #7: 0x000000010e1fd8b4 libclang_rt.asan_iossim_dynamic.dylib`__wrap_dispatch_async_block_invoke + 260
frame #8: 0x0000000112d36ef9 libdispatch.dylib`_dispatch_call_block_and_release + 12
frame #9: 0x0000000112d5749b libdispatch.dylib`_dispatch_client_callout + 8
frame #10: 0x0000000112d3f34b libdispatch.dylib`_dispatch_main_queue_callback_4CF + 1738
frame #11: 0x0000000111a813e9 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
frame #12: 0x0000000111a42939 CoreFoundation`__CFRunLoopRun + 2073
frame #13: 0x0000000111a41e98 CoreFoundation`CFRunLoopRunSpecific + 488
frame #14: 0x00000001144bdad2 GraphicsServices`GSEventRunModal + 161
frame #15: 0x000000010f85b676 UIKit`UIApplicationMain + 171
frame #16: 0x000000010dbd8e8f App`main(argc=1, argv=0x00007fff520485c0) + 111 at main.m:9
frame #17: 0x0000000112d8b92d libdyld.dylib`start + 1

Async stack trace across queues


-[NSConcreteTextStorage release]: message sent to deallocated instance 0x612002ddaa40

thread #1: tid = 0xb00610, 0x000000010c9fdeaf CoreFoundation`___forwarding___ + 767, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x000000010c9fdeaf CoreFoundation`___forwarding___ + 767
frame #1: 0x000000010c9fdb28 CoreFoundation`__forwarding_prep_0___ + 120
frame #2: 0x0000000108de1178 App`-[RCTText .cxx_destruct](self=0x0000614000409840, _cmd=".cxx_destruct") + 104 at RCTText.m:16
frame #3: 0x000000010c0c67bb libobjc.A.dylib`object_cxxDestructFromClass(objc_object*, objc_class*) + 127
frame #4: 0x000000010c0d1390 libobjc.A.dylib`objc_destructInstance + 93
frame #5: 0x000000010cab07c6 CoreFoundation`-[NSObject(NSObject) __dealloc_zombie] + 150
frame #6: 0x000000010a9df4b9 UIKit`-[UIResponder dealloc] + 130
frame #7: 0x000000010a86e2cf UIKit`-[UIView dealloc] + 1557
frame #8: 0x0000000108ddb0e0 App`-[RCTText dealloc](self=0x0000614000409840, _cmd="dealloc") + 432 at RCTText.m:42
frame #9: 0x000000010c0dc0b8 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 488
frame #10: 0x000000010c9959c6 CoreFoundation`_CFAutoreleasePoolPop + 22
frame #11: 0x000000010c9c9941 CoreFoundation`__CFRunLoopRun + 2081
frame #12: 0x000000010c9c8e98 CoreFoundation`CFRunLoopRunSpecific + 488
frame #13: 0x000000010f444ad2 GraphicsServices`GSEventRunModal + 161
frame #14: 0x000000010a7e2676 UIKit`UIApplicationMain + 171
frame #15: 0x0000000108b5fe8f App`main(argc=1, argv=0x00007fff570c15c0) + 111 at main.m:9
frame #16: 0x000000010dd1292d libdyld.dylib`start + 1

@ide
Copy link
Contributor Author

ide commented Oct 2, 2015

@nicklockwood Have you encountered dealloc race conditions before? Thought you may have some insight on what's going on here and how to fix it.

I read up on this class of race conditions and there's not a whole lot out there, but most of the discussion was around how weak references aren't zeroed out before deallocation. It didn't look like that was the case here since the problematic NSTextStorage is strongly referenced. Maybe there's a weak reference to the RCTText and that's cascading down to affect the deallocation of the NSTextStorage?

There were also a post about NSNotificationCenter and dealloc (http://inessential.com/2013/12/20/observers_and_thread_safety) but that didn't seem relevant to this problem since neither RCTText nor NSTextStorage is subscribing to RCT notifications.

@ide
Copy link
Contributor Author

ide commented Oct 8, 2015

I dug in some more and potentially narrowed it down to the fact that we share the same cached NSTextStorage between RCTShadowText's RCTMeasure and the main thread (RCTText). It makes sense to me if that's the issue since NSTextStorage isn't thread-safe and I'll keep investigating.

@nicklockwood
Copy link
Contributor

That's true, but we shouldn't ever be accessing the same instance concurrently. The sequence is:

  1. shadow thread creates and configures a new text storage object
  2. Main thread renders text using that text storage object

The shadow thread never modifies the same text storage instance after first creating it, and the main thread never gets access to the storage until the shadow thread has finished with it.

At least, that's the way I designed it. It's possible there's a bug, or I've got some misconception.

@ide
Copy link
Contributor Author

ide commented Oct 8, 2015

The reason I thought that the shadow thread could access the NSTextStorage after it was passed to the main thread was because I saw the crash go away when I commented out the code that get/set _cachedTextStorage. It does appear that -[RCTShadowText fillCSSNode] isn't called after the NSTextStorage instance is passed to RCTText instance, so that isn't the case. Fingers crossed that #3279 fixes things -- I haven't seen the crash with that patch =)

ide added a commit that referenced this issue Oct 8, 2015
…lityManager

Summary: When you reload and create a new bridge, one of the things that happens during setup is that the RCTAccessibilityManager fires a notification. The old bridge would receive this notification from the new bridge's RCTAccessibilityManager, which we don't want, especially because the two are running on different shadow queues.

I believe this led to a gnarly crash in NSConcreteTextStorage because RCTMeasure in RCTShadowText.m was getting called for the old RCTText (getting destroyed) from a notification fired from the new shadow queue. The fix is for the UIManager to handle notifications only from its bridge's RCTAccessibilityManager. See #2001 for the kinds of crashes we were seeing.
Closes #3279

Reviewed By: @​svcscm

Differential Revision: D2521652

Pulled By: @nicklockwood

fb-gh-sync-id: a4ffe3ef8304667727e573e2a2e8b716e1d2f3e1
liaohuqiu pushed a commit to liaohuqiu/react-native that referenced this issue Oct 9, 2015
…lityManager

Summary: When you reload and create a new bridge, one of the things that happens during setup is that the RCTAccessibilityManager fires a notification. The old bridge would receive this notification from the new bridge's RCTAccessibilityManager, which we don't want, especially because the two are running on different shadow queues.

I believe this led to a gnarly crash in NSConcreteTextStorage because RCTMeasure in RCTShadowText.m was getting called for the old RCTText (getting destroyed) from a notification fired from the new shadow queue. The fix is for the UIManager to handle notifications only from its bridge's RCTAccessibilityManager. See facebook#2001 for the kinds of crashes we were seeing.
Closes facebook#3279

Reviewed By: @​svcscm

Differential Revision: D2521652

Pulled By: @nicklockwood

fb-gh-sync-id: a4ffe3ef8304667727e573e2a2e8b716e1d2f3e1
@ide
Copy link
Contributor Author

ide commented Oct 11, 2015

Closing this since we haven't seen the crash after a couple of days of regular use with the merged diff.

@ide ide closed this as completed Oct 11, 2015
MattFoley pushed a commit to skillz/react-native that referenced this issue Nov 9, 2015
…lityManager

Summary: When you reload and create a new bridge, one of the things that happens during setup is that the RCTAccessibilityManager fires a notification. The old bridge would receive this notification from the new bridge's RCTAccessibilityManager, which we don't want, especially because the two are running on different shadow queues.

I believe this led to a gnarly crash in NSConcreteTextStorage because RCTMeasure in RCTShadowText.m was getting called for the old RCTText (getting destroyed) from a notification fired from the new shadow queue. The fix is for the UIManager to handle notifications only from its bridge's RCTAccessibilityManager. See facebook#2001 for the kinds of crashes we were seeing.
Closes facebook#3279

Reviewed By: @​svcscm

Differential Revision: D2521652

Pulled By: @nicklockwood

fb-gh-sync-id: a4ffe3ef8304667727e573e2a2e8b716e1d2f3e1
Crash-- pushed a commit to Crash--/react-native that referenced this issue Dec 24, 2015
…lityManager

Summary: When you reload and create a new bridge, one of the things that happens during setup is that the RCTAccessibilityManager fires a notification. The old bridge would receive this notification from the new bridge's RCTAccessibilityManager, which we don't want, especially because the two are running on different shadow queues.

I believe this led to a gnarly crash in NSConcreteTextStorage because RCTMeasure in RCTShadowText.m was getting called for the old RCTText (getting destroyed) from a notification fired from the new shadow queue. The fix is for the UIManager to handle notifications only from its bridge's RCTAccessibilityManager. See facebook#2001 for the kinds of crashes we were seeing.
Closes facebook#3279

Reviewed By: @​svcscm

Differential Revision: D2521652

Pulled By: @nicklockwood

fb-gh-sync-id: a4ffe3ef8304667727e573e2a2e8b716e1d2f3e1
@facebook facebook locked as resolved and limited conversation to collaborators Jul 22, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 22, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests