iosopengl-esopengl-es-2.0glkview

Modifying UIVIew above GLKView causing crashes


I have random crashes in my application. Eventually i figured out that the crashes happen when i add UIVIew elements and modify their center position. The crashes don't happen on IPad Air 2 but the scenario is consistent on IPad Air - when the UIViews are on, there are crashes and the crashes disappear when the views are removed. The crashes happens asynchronously with the following stack:

#0  0x0000000190bf1f28 in gpus_ReturnGuiltyForHardwareRestart ()
#1  0x0000000190bf2ec4 in gpusSubmitDataBuffers ()
#2  0x0000000189d56254 in gliPresentViewES_Exec ()
#3  0x0000000189d5616c in gliPresentViewES ()
#4  0x0000000189d63cbc in -[EAGLContext presentRenderbuffer:] ()
#5  0x0000000101ff8078 in EAGLContext_presentRenderbuffer(EAGLContext*, objc_selector*, unsigned long) ()
#6  0x00000001877dc638 in -[GLKView _display:] ()
#7  0x000000018b55eeb8 in CA::Layer::display() ()
#8  0x000000018b5413a0 in CA::Layer::display_if_needed(CA::Transaction*) ()
#9  0x000000018b54108c in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#10 0x000000018b54071c in CA::Context::commit_transaction(CA::Transaction*) ()
#11 0x000000018b540470 in CA::Transaction::commit() ()
#12 0x000000018b539c10 in CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) ()
#13 0x000000018666f3f8 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#14 0x000000018666d19c in __CFRunLoopDoObservers ()
#15 0x000000018666d5cc in __CFRunLoopRun ()
#16 0x000000018659d280 in CFRunLoopRunSpecific ()
#17 0x00000001915500cc in GSEventRunModal ()
#18 0x000000018bd8adf8 in UIApplicationMain ()
#19 0x000000010077d36c in main at /Code/splinedr/Splinedr/main.mm:18
#20 0x000000019b7fa8b8 in start ()

I render OpenGL using calls to [self.view needDisplay] and modify UIViews right before that.

How should i deal with this issue?


Solution

  • Make sure your GLKViewController is paused, and that the GLKView's enableSetNeedsDisplay is set to 1. If those are already set correctly, it might be that you are calling setNeedsDisplay on a background thread, and that your subviews are triggering conflicting calls on the main thread. Make sure all of your calls to setNeedsDisplay are called from the main thread. One easy way to verify is to just put a print statement next to each call.

    [self.view setNeedsDisplay];
    printf("%s\n",dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); 
    

    Another alternative is to set enableSetNeedsDisplay to zero and just call [self.view display] directly. You might have to add a couple of display calls here and there when views appear and frames change, but it ultimately will give you more control. If it doesn't solve the problem entirely, it will at least make it easier to follow the stack trace as all draw calls will originate from one of your calls to display.