Metal Background Rendering caused NSInternalInconsistencyException

Hi, I have been getting the following crash in my app which has a Custom Metal Render Engine

CoreFoundation                   -[__NSSetM clumpingFactor] + 264
libobjc.A.dylib                  __objc_empty_cache + 888
CoreAutoLayout                   DA979160-E330-3C35-BF6F-D3248DCC3246 + 67536
CoreAutoLayout                   DA979160-E330-3C35-BF6F-D3248DCC3246 + 68272
UIKitCore                        __OBJC_$_INSTANCE_METHODS__UIDatePickerCalendarTimeLabel + 600
UIKitCore                        __OBJC_$_INSTANCE_METHODS__UINavigationBarStarkVisualStyle + 100
UIKitCore                        ___79+[UISwitchModernVisualElement _modernThumbImageWithColor:mask:traitCollection:]_block_invoke_2 + 204
UIKitCore                        -[UISwitchModernVisualElement _switchTrackPositionAnimationWithFromValue:toValue:on:] + 388
UIKitCore                        -[UISwitchModernVisualElement _effectiveGradientImage] + 128
UIKitCore                        __OBJC_$_INSTANCE_METHODS__UISearchBarVisualProviderLegacy + 1924
QuartzCore                       CA::Layer::add_animation(CAAnimation*, __CFString const*) + 72
QuartzCore                       CA::Layer::remove_sublayer(CA::Transaction*, CALayer*) + 272
QuartzCore                       CA::OGL::Context::draw_elements(CA::OGL::PrimitiveMode, unsigned int, unsigned short const*, CA::OGL::Vertex const*, unsigned int, unsigned int, CA::OGL::ClipPlane const*) + 60
QuartzCore                       CAML::cgcolor_end(CAML::Context*, CAML::State*, char*, unsigned long) + 1252
QuartzCore                       native_window_swap(_EAGLNativeWindowObject*, unsigned int, double) + 712
QuartzCore                       -[CAStateControllerAnimation initWithLayer:key:] + 52
CoreFoundation                   ___CFSocketSetSocketReadBufferAttrs + 444
CoreFoundation                   __CFNonObjCEqual + 8
CoreFoundation                   __CFRelease + 952
Foundation                       4E7D1FF6-6B64-3833-9E60-CC662AFE2647 + 36236
danmu                            -[DMEngineBase runMetalThread] (in DMEngineBase.mm:148)
Foundation                       4E7D1FF6-6B64-3833-9E60-CC662AFE2647 + 1549068
libsystem_pthread.dylib          _pthread_rwlock_unlock$VARIANT$armv81 + 160
libsystem_pthread.dylib          __pthread_create + 1196

this crash seems caused by the Metal Thread Rendering which triggered a CoreAnimation drawing and finally crashed at CoreAutoLayout internal method :

Crashed View : appEnterForeground
Exception Name : NSInternalInconsistencyException
Exception Reason :
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.

In the latest Version I have been trying solved this crash by add some protected like this :

- (void)runMetalThread
{
  NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
  [_displayLink addToRunLoop:runLoop forMode:DMMetalRunLoopModelFrame];

  BOOL continueRunLoop = YES;
  while (continueRunLoop)
  {
    @autoreleasepool
    {
      [runLoop runMode:DMMetalRunLoopModelFrame beforeDate:[NSDate distantFuture]];
    }
    continueRunLoop = _continueRunLoop;
  }
}

- (void)onBulletDraw:(CADisplayLink*)displayLink
{
  self.renderer.stoped = !_isActive || _stoped;
  self.renderer.paused = _isPaused;
  [self.renderer onDanmuDraw:displayLink];
}

#pragma mark - Notification
- (void)willResignActive
{
  self.isActive = NO;
  MTLog(@"metal# engine %@ resign active", self);
}

- (void)didBecomeActive
{
  //Protected by delay active the metal engine after app state didBecomeActive
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    if (UIApplication.sharedApplication.applicationState == UIApplicationStateActive) {
      self.isActive = YES;
      MTLog(@"metal# engine %@ become active", self);
    }else{
      MTLog(@"metal# engine still inactive after 0.7s");
    }
  });
}

this protected has make sure to STOPed the Metal Render after the app resign active, and seems has some effect which reduced 84% crashes on my released app . but it did not completely solve this problem still has 16% crashes in some unknown scene . I have been checked all my Metal Rendering thread code , I can be guaranteed that no method will trigger CoreAnimation drawing in this metal thread. So is there has an Perfective Solution of this bug ?

Add a Comment