Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Need global locking in ASTextNodeRenderer. #29

Closed
toulouse opened this issue Sep 24, 2014 · 5 comments
Closed

Need global locking in ASTextNodeRenderer. #29

toulouse opened this issue Sep 24, 2014 · 5 comments
Labels

Comments

@toulouse
Copy link
Contributor

Repro project:
http://www.atoulou.se/Repro.tar.bz2

Very barebones. Remember to set zombies to on. Tested using iPhone 5s (7.1) Simulator on OS X 10.9.

Crash 1 (almost every time):

(lldb) thread backtrace
* thread #4: tid = 0x18149, 0x00000001091accc4 CoreFoundation`___forwarding___ + 772, queue = 'com.facebook.AsyncDisplayKit.ASRangeController.sizingQueue', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x00000001091accc4 CoreFoundation`___forwarding___ + 772
    frame #1: 0x00000001091ac938 CoreFoundation`__forwarding_prep_0___ + 120
    frame #2: 0x000000010d980ade UIFoundation`-[NSTypesetter _updateParagraphStyleCache:] + 319
    frame #3: 0x000000010d981b5c UIFoundation`-[NSTypesetter getLineFragmentRect:usedRect:forParagraphSeparatorGlyphRange:atProposedOrigin:] + 633
    frame #4: 0x000000010d98430c UIFoundation`-[NSTypesetter _layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:maxCharacterIndex:nextGlyphIndex:nextCharacterIndex:] + 7720
    frame #5: 0x000000010d984872 UIFoundation`-[NSTypesetter layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:nextGlyphIndex:] + 105
    frame #6: 0x000000010d92b6fc UIFoundation`-[NSATSTypesetter layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:nextGlyphIndex:] + 460
  * frame #7: 0x000000010d94d313 UIFoundation`-[NSLayoutManager insertTextContainer:atIndex:] + 926
    frame #8: 0x000000010895250d Repro`-[ASTextNodeRenderer _initializeTextKitComponentsWithAttributedString:](self=0x00007f9259d004f0, _cmd=0x000000010896ba33, attributedString=0x0000000000000000) + 957 at ASTextNodeRenderer.mm:90
    frame #9: 0x0000000108952115 Repro`-[ASTextNodeRenderer _initializeTextKitComponentsIfNeeded](self=0x00007f9259d004f0, _cmd=0x000000010896bb70) + 101 at ASTextNodeRenderer.mm:69
    frame #10: 0x0000000108952d94 Repro`-[ASTextNodeRenderer size](self=0x00007f9259d004f0, _cmd=0x0000000110e50d67) + 36 at ASTextNodeRenderer.mm:169
    frame #11: 0x0000000108947c54 Repro`-[ASTextNode calculateSizeThatFits:](self=0x00007f9259e21a80, _cmd=0x000000010896804b, constrainedSize=CGSize at 0x00000001157ec948) + 2548 at ASTextNode.mm:184
    frame #12: 0x000000010891e0c4 Repro`-[ASDisplayNode measure:](self=0x00007f9259e21a80, _cmd=0x0000000108967ff7, constrainedSize=CGSize at 0x00000001157ecab8) + 660 at ASDisplayNode.mm:323
    frame #13: 0x0000000108901694 Repro`-[ReproNode calculateSizeThatFits:](self=0x00007f9259e21950, _cmd=0x000000010896804b, constrainedSize=CGSize at 0x00000001157ecb30) + 116 at ReproNode.m:33
    frame #14: 0x000000010891e0c4 Repro`-[ASDisplayNode measure:](self=0x00007f9259e21950, _cmd=0x0000000108967ff7, constrainedSize=CGSize at 0x00000001157ecc98) + 660 at ASDisplayNode.mm:323
    frame #15: 0x0000000108941fb5 Repro`__34-[ASRangeController sizeNextBlock]_block_invoke_2(.block_descriptor=<unavailable>) + 213 at ASRangeController.mm:538
    frame #16: 0x000000010ab6a851 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #17: 0x000000010ab7d72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #18: 0x000000010ab6beab libdispatch.dylib`_dispatch_async_redirect_invoke + 174
    frame #19: 0x000000010ab7d72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #20: 0x000000010ab6db27 libdispatch.dylib`_dispatch_root_queue_drain + 380
    frame #21: 0x000000010ab6dd12 libdispatch.dylib`_dispatch_worker_thread2 + 40
    frame #22: 0x000000010af1bef8 libsystem_pthread.dylib`_pthread_wqthread + 314
    frame #23: 0x000000010af1efb9 libsystem_pthread.dylib`start_wqthread + 13
(lldb) 

Crash 2 (uncommon?):

(lldb) thread backtrace
* thread #4: tid = 0x17667, 0x0000000000000000, queue = 'com.facebook.AsyncDisplayKit.ASRangeController.sizingQueue', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000000000000
    frame #1: 0x00000001147cd893 UIFoundation`+[NSTextStorage allocWithZone:] + 33
  * frame #2: 0x000000010f7cb219 Repro`-[ASTextNodeRenderer _initializeTextKitComponentsWithAttributedString:](self=0x00007f880d110d50, _cmd=0x000000010f7e4a33, attributedString=0x0000000000000000) + 201 at ASTextNodeRenderer.mm:78
    frame #3: 0x000000010f7cb115 Repro`-[ASTextNodeRenderer _initializeTextKitComponentsIfNeeded](self=0x00007f880d110d50, _cmd=0x000000010f7e4b70) + 101 at ASTextNodeRenderer.mm:69
    frame #4: 0x000000010f7cbd94 Repro`-[ASTextNodeRenderer size](self=0x00007f880d110d50, _cmd=0x0000000117cb0d67) + 36 at ASTextNodeRenderer.mm:169
    frame #5: 0x000000010f7c0c54 Repro`-[ASTextNode calculateSizeThatFits:](self=0x00007f880ad16d70, _cmd=0x000000010f7e104b, constrainedSize=CGSize at 0x000000011c539948) + 2548 at ASTextNode.mm:184
    frame #6: 0x000000010f7970c4 Repro`-[ASDisplayNode measure:](self=0x00007f880ad16d70, _cmd=0x000000010f7e0ff7, constrainedSize=CGSize at 0x000000011c539ab8) + 660 at ASDisplayNode.mm:323
    frame #7: 0x000000010f77a694 Repro`-[ReproNode calculateSizeThatFits:](self=0x00007f880ad166b0, _cmd=0x000000010f7e104b, constrainedSize=CGSize at 0x000000011c539b30) + 116 at ReproNode.m:33
    frame #8: 0x000000010f7970c4 Repro`-[ASDisplayNode measure:](self=0x00007f880ad166b0, _cmd=0x000000010f7e0ff7, constrainedSize=CGSize at 0x000000011c539c98) + 660 at ASDisplayNode.mm:323
    frame #9: 0x000000010f7bafb5 Repro`__34-[ASRangeController sizeNextBlock]_block_invoke_2(.block_descriptor=<unavailable>) + 213 at ASRangeController.mm:538
    frame #10: 0x00000001119ca851 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #11: 0x00000001119dd72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #12: 0x00000001119cbeab libdispatch.dylib`_dispatch_async_redirect_invoke + 174
    frame #13: 0x00000001119dd72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #14: 0x00000001119cdb27 libdispatch.dylib`_dispatch_root_queue_drain + 380
    frame #15: 0x00000001119cdd12 libdispatch.dylib`_dispatch_worker_thread2 + 40
    frame #16: 0x0000000111d72ef8 libsystem_pthread.dylib`_pthread_wqthread + 314
    frame #17: 0x0000000111d75fb9 libsystem_pthread.dylib`start_wqthread + 13
(lldb) list
   88     _textContainer.lineBreakMode = _truncationMode;
   89   
   90     [_layoutManager addTextContainer:_textContainer];
   91   
   92     [self _invalidateLayout];
   93   }
   94   
   95   #pragma mark - Layout Initialization
   96   
   97   - (void)_invalidateLayout
@secretiverhyme secretiverhyme changed the title Crash on barebones test project due to over-release Rare crash in -[ASTextNode measure:] Sep 24, 2014
@secretiverhyme
Copy link
Contributor

This code snippet in an empty project is sufficient to reproduce the zombie:

for (NSInteger i = 0; i < 200; i++) {
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    ASTextNode *node = [[ASTextNode alloc] init];
    [node measure:CGSizeMake(320, 480)];
    NSLog(@"result: %@", NSStringFromCGSize(node.calculatedSize));
  });
}

@secretiverhyme
Copy link
Contributor

As is this:

  for (NSInteger i = 0; i < 200; i++) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
      NSTextStorage *textStorage = [[NSTextStorage alloc] init];
      NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
      [textStorage addLayoutManager:layoutManager];
      NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(320, 480)];
      [layoutManager addTextContainer:textContainer];
      NSLog(@"%zd", i);
    });
  }

Doesn't repro on a serial queue.

@ocrickard
Copy link
Contributor

Indicating we need a global sync lock on these parts. We were really hoping that this wasn't necessary... but I guess CTFrameSetterCreate... methods also aren't globally threadsafe, so honestly not too surprised.

@ocrickard
Copy link
Contributor

So now we need to narrow down on exactly which collection of methods are not globally threadsafe, and lock on the bare minimum of computational time.

@secretiverhyme
Copy link
Contributor

rdar://18448377 filed.

@secretiverhyme secretiverhyme changed the title Rare crash in -[ASTextNode measure:] Need global locking in ASTextNodeRenderer. Sep 24, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants