Texture icon indicating copy to clipboard operation
Texture copied to clipboard

XCTests using Texture/AsyncDisplayKit deadlock during initialisation when targeting iOS 15

Open benniebotha opened this issue 4 years ago • 22 comments

While running the test, AsyncDisplayKit hangs before any tests run when iOS 15 is used as the test target. It appears to hang inside -[UIView init] which indicates there may be an issue with UIKit itself. This issue has been raised with Apple, but implementing a fix in Texture is needed in the meantime.

In AsyncDisplayKit we can see that the hang occurs in the following functions:

__attribute__((constructor)) static void ASLoadFrameworkInitializer(void)
{
  ASInitializeFrameworkMainThread();
}
void ASInitializeFrameworkMainThread(void)
{
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    ASDisplayNodeCAssertMainThread();
    // Ensure these values are cached on the main thread before needed in the background.
    if (ASActivateExperimentalFeature(ASExperimentalLayerDefaults)) {
      // Nop. We will gather default values on-demand in ASDefaultAllowsGroupOpacity and ASDefaultAllowsEdgeAntialiasing
    } else {
      CALayer *layer = [[[UIView alloc] init] layer];
      allowsGroupOpacityFromUIKitOrNil = @(layer.allowsGroupOpacity);
      allowsEdgeAntialiasingFromUIKitOrNil = @(layer.allowsEdgeAntialiasing);
    }
    ASNotifyInitialized();
#if AS_SIGNPOST_ENABLE
    _ASInitializeSignpostObservers();
#endif
  });

It appears the hang is during the call to [[UIView alloc] init] inside the dispatch_once.

benniebotha avatar Sep 22 '21 04:09 benniebotha

@benniebotha I can confirm i'm seeing the same thing. Would you be able to link to the Apple issue for tracking? Oddly I'm also seeing the same result very occasionaly running the app itself. It will freeze on a splash screen before didFinishLaunchingWithOptions is called and will prevent the app launching at all.

@nguyenhuy I don't suppose one of the team could look into this?

foxware00 avatar Sep 22 '21 09:09 foxware00

@benniebotha changing the ASInitializeFrameworkMainThread function to the following allows the tests to pass. I believe it's also the defaults fetched from the layer. I don't override this stuff in the .plist so it's an acceptable workaround for the meantime.

void ASInitializeFrameworkMainThread(void)
{
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    ASDisplayNodeCAssertMainThread();
    // Ensure these values are cached on the main thread before needed in the background.
    if (ASActivateExperimentalFeature(ASExperimentalLayerDefaults)) {
      // Nop. We will gather default values on-demand in ASDefaultAllowsGroupOpacity and ASDefaultAllowsEdgeAntialiasing
    } else {
      allowsGroupOpacityFromUIKitOrNil = @(YES); // Use default values here instead of loading the layer
      allowsEdgeAntialiasingFromUIKitOrNil = @(NO);
    }
    ASNotifyInitialized();
#if AS_SIGNPOST_ENABLE
    _ASInitializeSignpostObservers();
#endif
  });
}

foxware00 avatar Sep 22 '21 09:09 foxware00

Thanks @foxware00 for looking into it further. The fact that it is occasionally happening outside of tests is even more concerning! I raised the issue under the dev tools feedback that is unfortunately not public. 😞 Your solution would does seem to work yes. Another work around seems to be activating the ASExperimentalLayerDefaults experiment. I haven't worked on Texture a lot, could you point me to the documentation on how these experiments work?

benniebotha avatar Sep 23 '21 01:09 benniebotha

Thanks @foxware00 for looking into it further. The fact that it is occasionally happening outside of tests is even more concerning! I raised the issue under the dev tools feedback that is unfortunately not public. 😞 Your solution would does seem to work yes. Another work around seems to be activating the ASExperimentalLayerDefaults experiment. I haven't worked on Texture a lot, could you point me to the documentation on how these experiments work?

Yes it's very concerning, I can't say 100% that it's Texture during normal boot as i'm currently unable to get a spindump when it happens. However the result (freezing before the app boots without any logs) is identical to that shown when running UITests

In terms of the Experimental flags, I'm not 100% sure having not used them in the past. Which package manager are you using, you can point Cocoapods at a github fork with the changes mentioned above if it would satisfy you in the meantime?

foxware00 avatar Sep 23 '21 08:09 foxware00

@nguyenhuy I've had a response from eskimo at Apple and has indicated that the framework intialisation is at fault. He has suggested a couple of work arounds such as lazily initalizing the framework. Are you able to take a look at this and see if there is anything we can do?

https://developer.apple.com/forums//thread/689592?answerId=688696022&replyId=688696022

foxware00 avatar Sep 23 '21 10:09 foxware00

Any progress on this issue as we also experience it and we r heavy dependent on Texture. (or possible work around would )

MikePendo avatar Sep 26 '21 05:09 MikePendo

same issue here

MaximShnirman avatar Sep 26 '21 07:09 MaximShnirman

Thanks @foxware00 for raising it on the Apple forum. I got the experiment working as well as making those temporary changes in our fork. That should do for now thanks.

Hopefully it will get solved quickly on the main repo.

benniebotha avatar Sep 26 '21 23:09 benniebotha

@benniebotha the solution we've aludded too seems to fix unit tests but still happens in the main app for a subset of users.

It would be good to have some weigh in from some of the authors as my knowledge of Objective-C and framework initalisers is limited.

@garrettmoon @nguyenhuy @appleguy @Adlai-Holler

foxware00 avatar Sep 27 '21 07:09 foxware00

Thanks @foxware00 for raising it on the Apple forum. I got the experiment working as well as making those temporary changes in our fork. That should do for now thanks.

Hopefully it will get solved quickly on the main repo.

@benniebotha It might be worth also rasing a compatability bug with Apple, the more people shouting the more likely they are to fix it.

foxware00 avatar Sep 27 '21 11:09 foxware00

https://github.com/TextureGroup/Texture/pull/2032 I just open Pull-Request. It replace attribute from constructor to destructor for run after main on running unit test

GeekTree0101 avatar Sep 28 '21 01:09 GeekTree0101

same issue here

galgord avatar Sep 30 '21 07:09 galgord

experiencing similar issue

noambartouv avatar Sep 30 '21 21:09 noambartouv

Really curious why this only/always happen in unit test but not in application itself

jeffersonsetiawan avatar Oct 04 '21 07:10 jeffersonsetiawan

Really curious why this only/always happen in unit test but not in application itself

Any why only starting with iOS 15 / Xcode 13

brandtdaniels avatar Oct 04 '21 19:10 brandtdaniels

Same here

dimanitm avatar Oct 11 '21 10:10 dimanitm

I still don't understand how that related to the tests? Why the test got stuck even though the Texture related code wasn't invoke, (I see some dynamic invocation when loading the library I am not sure why its needed as fo example in our test cases we don't even use Texture so its kinda redundant and now causing some strange issues). Apparently I see some strange issue with cornerradius with and without that patch Ok I have looked a little bit in the code and apparently u r initializing some UI components on load time for instance here: ASInitializeFrameworkMainThread That what cause some issues on our side in general according to Apple docs u should not init any heavy object during load time (not sure why it was done that way, removing the initialization to more proper place seems to resolve the issue).

MikePendo avatar Nov 28 '21 06:11 MikePendo

Same here

lucasromanomr avatar Dec 08 '21 19:12 lucasromanomr

https://github.com/TextureGroup/Texture/pull/2032 has been merged, so this issue has got fixed and could be closed. Check out the current master branch.

denkeni avatar Dec 09 '21 15:12 denkeni

Hey! It looks like this pr https://github.com/TextureGroup/Texture/pull/2032 does not solve the issue. @foxware00 's this solution works.

musakokcen avatar Dec 20 '21 14:12 musakokcen

We're experiencing the same issue. Is there any way we can assist here, to resolve this?

christiankm avatar Jun 17 '22 05:06 christiankm

Is there any update on this getting fixed in a release?

richieshilton avatar Sep 01 '22 00:09 richieshilton