iOS app crashes on resuming

(SEE UPDATE AT THE BOTTOM)

Recently I’ve started getting a weird and rare crash of my iPhone app when it returns from background. The crash log consists of system calls only:

  • AFNetworking and jSON
  • UIDocumentInteractionController not working in iPad Simulator (XCode 3.2.3)
  • How to Edit Empty Spaces of Left, Right UIBarButtonItem in UINavigationBar
  • How to record sound produced by mixer unit output (iOS Core Audio & Audio Graph)
  • Enable download in inAppBrowser - Phonegap / Cordova
  • How to speed up UI test cases in Xcode?
  • Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
    Exception Codes: KERN_INVALID_ADDRESS at 0x00000138
    Crashed Thread:  0
    
    Thread 0 name:  Dispatch queue: com.apple.main-thread
    Thread 0 Crashed:
    0   libobjc.A.dylib                 0x34c715b0 objc_msgSend + 16
    1   CoreFoundation                  0x368b7034 _CFXNotificationPost + 1424
    2   Foundation                      0x34379d8c -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
    3   UIKit                           0x37ddfec2 -[UIApplication _handleApplicationResumeEvent:] + 1290
    4   UIKit                           0x37c37d5c -[UIApplication handleEvent:withNewEvent:] + 1288
    5   UIKit                           0x37c376d0 -[UIApplication sendEvent:] + 68
    6   UIKit                           0x37c3711e _UIApplicationHandleEvent + 6150
    7   GraphicsServices                0x36dea5a0 _PurpleEventCallback + 588
    8   CoreFoundation                  0x3693b680 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
    9   CoreFoundation                  0x3693aee4 __CFRunLoopDoSources0 + 208
    10  CoreFoundation                  0x36939cb2 __CFRunLoopRun + 642
    11  CoreFoundation                  0x368aceb8 CFRunLoopRunSpecific + 352
    12  CoreFoundation                  0x368acd44 CFRunLoopRunInMode + 100
    13  GraphicsServices                0x36de92e6 GSEventRunModal + 70
    14  UIKit                           0x37c8b2fc UIApplicationMain + 1116
    15  [MyAppName]                     0x00083d60 main (main.m:20)
    16  [MyAppName]                     0x00080304 start + 36
    

    This might look like a zombie object being called on UIApplicationWillEnterForegroundNotification or UIApplicationDidBecomeActiveNotification (guessing by _handleApplicationResumeEvent in stack trace and the time when it crashes), but:

    1. None of my classes register for UIApplicationDidBecomeActiveNotification, and only a couple of singletons (that stay alive forever) register for UIApplicationWillEnterForegroundNotification;
    2. I’ve done some experimenting, and it turns out that posting UIApplicationWillEnterForegroundNotification goes from [UIApplication _sendWillEnterForegroundCallbacks:], and it isn’t in the crash log.

    For me, all this implies a bug in some library I’m using, or a system bug, and the crash occurred once on iOS 5.1.1 (release build), once on iOS 6.0 (release build) and once on iOS 6.0 (debug build). I scanned every library I’m using and have access to the source code for, and they aren’t registering for neither UIApplicationWillEnterForegroundNotification nor UIApplicationDidBecomeActiveNotification. The only library I don’t have access to is TestFlight, but the crash occurred on both 1.0 and 1.1 versions of TestFlight, and I’ve been using the former for quite a while now, without such problems.
    So, summing up, I have no idea why has this crash come up and what’s it coming from. Any ideas?

    UPDATE 1

    I’ve investigated the issue a bit deeper, thanks to DarthMike and matt for their help. By using notification center callback and logging stack trace, I’ve discovered that this exact stack comes up when and only when UIApplicationResumedNotification notification is fired as a part of returning from background. And guess what – it’s some “private” notification and it doesn’t have a public identifier counterpart. It doesn’t have userInfo and its object is UIApplication (as many other notifications that are posted before this). Obviously I don’t use it, neither does any library I have source code for. I can’t even find any reasonable mentioning of it in the Internet! I also highly doubt that TestFlight is the culprit, because crash happened during debug too, and I don’t “take off” TestFlight in debug mode.

    Here’s the stack trace for receiving UIApplicationResumedNotification. The offsets are all the same but with a constant byte offset (2 or 4, depending on the library – probably because it’s a debug stack tracing, not release):

    0   [MyAppName]                         0x0016f509 NotificationsCallback + 72
    1   CoreFoundation                      0x3598ce25 __CFNotificationCenterAddObserver_block_invoke_0 + 124
    2   CoreFoundation                      0x35911037 _CFXNotificationPost + 1426
    3   Foundation                          0x333d3d91 -[NSNotificationCenter postNotificationName:object:userInfo:] + 72
    4   UIKit                               0x36e39ec7 -[UIApplication _handleApplicationResumeEvent:] + 1294
    5   UIKit                               0x36c91d61 -[UIApplication handleEvent:withNewEvent:] + 1292
    6   UIKit                               0x36c916d5 -[UIApplication sendEvent:] + 72
    7   UIKit                               0x36c91123 _UIApplicationHandleEvent + 6154
    8   GraphicsServices                    0x35e445a3 _PurpleEventCallback + 590
    9   CoreFoundation                      0x35995683 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
    10  CoreFoundation                      0x35994ee9 __CFRunLoopDoSources0 + 212
    11  CoreFoundation                      0x35993cb7 __CFRunLoopRun + 646
    12  CoreFoundation                      0x35906ebd CFRunLoopRunSpecific + 356
    13  CoreFoundation                      0x35906d49 CFRunLoopRunInMode + 104
    14  GraphicsServices                    0x35e432eb GSEventRunModal + 74
    15  UIKit                               0x36ce5301 UIApplicationMain + 1120
    16  [MyAppName]                         0x000aa603 main + 390
    17  [MyAppName]                         0x000a41b0 start + 40
    

    NotificationsCallback is an “observer” callback I’ve added for debug just for now.

    Just to prove a point, I’ve deliberately omitted a removeObserver: call from one of my objects to generate a zombie/exception, and stack trace still included _CFXNotificationPost + 1426 followed by a crash with EXC_BAD_ACCESS in objc_msgSend + 16, just as in my original crash.
    So this just means that someone has registered an observer for UIApplicationResumedNotification and haven’t removed it before the observer was deallocated. Based on the fact that I never registered for such a notification, I can assume that this crash is not my fault. Still the question remains – whose it is then? I wonder who actually registers for this notification anyway…

    UPDATE 2

    While I’m still waiting to see if there are any changes with this bug on the new version of my app, I’ve got another crash on the previous version caused by this. Turns out that whatever registers for UIApplicationResumedNotification, specifies selector _applicationResuming: for it. I doubt that’s of any use though.

    5 Solutions Collect From Internet About “iOS app crashes on resuming”

    I just ran into this issue and found a solution that did not involve removing notifications. In our case, there was old code that was doing this:

    - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
    {
      [searchBar resignFirstResponder];
      // other stuff
    }
    

    I do not know why we had this, but it is gone now and the crash is gone. It appears that in this case, resigning first responder while searchBarTextDidBeginEditing is being called orphans a notification on the search bar’s text edit field, and then we’d crash as soon as the view controller owning this UISearchBar was deallocated and we did the background / foreground dance.

    YMMV

    I had exactly the same stack trace in a crash report from a device running IOS 6.0.1. I managed to reproduce the problem on Simulator through the following pattern:

    • Put the application in the background
    • Simulate a memory warning from simulator menu
    • Bring the application back to the foreground

    After a lot of debugging I discovered that the _applicationResuming: message is sent to a UITextField which I am releasing as a reaction to Memory Warning. I tested the same pattern under IOS 5.1 but it didn’t cause a crash. For some reason in IOS 6 UITextField registers for ApplicationResumeEvent (maybe not always but after the keyboard has appeared).
    My workaround was to remove this object from NSNotificationCenter before releasing it:

    [[NSNotificationCenter defaultCenter] removeObserver:self.placeFld];
    self.placeFld = nil;
    

    Put a breakpoint on -[NSNotificationCenter postNotificationName:object:userInfo:]. It’s trying to send a notification to an object that isn’t there any more, or something like that. You may be mismanaging your own notifications or your own objects.

    Consider switching to ARC if you are not using it already.

    Use the static analyzer. It can find potential memory issues.

    Could be many things, but I think checking in code who registers for ANY UIApplication notification would be better. You don’t really know which notification triggers the error.

    Also, is any object retaining/holding strong reference on the AppDelegate? It may cause some weird retain cycle making this crash happen.

    I’ve never seen such a crash by XCode misbehaviour.

    EDIT: Pasting all notifications from header file. may be overkill but some could be sent on app resume/from background

    UIKIT_EXTERN NSString *const UIApplicationDidEnterBackgroundNotification       NS_AVAILABLE_IOS(4_0);
    UIKIT_EXTERN NSString *const UIApplicationWillEnterForegroundNotification      NS_AVAILABLE_IOS(4_0);
    UIKIT_EXTERN NSString *const UIApplicationDidFinishLaunchingNotification;
    UIKIT_EXTERN NSString *const UIApplicationDidBecomeActiveNotification;
    UIKIT_EXTERN NSString *const UIApplicationWillResignActiveNotification;
    UIKIT_EXTERN NSString *const UIApplicationDidReceiveMemoryWarningNotification;
    UIKIT_EXTERN NSString *const UIApplicationWillTerminateNotification;
    UIKIT_EXTERN NSString *const UIApplicationSignificantTimeChangeNotification;
    UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarOrientationNotification; // userInfo contains NSNumber with new orientation
    UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarOrientationNotification;  // userInfo contains NSNumber with old orientation
    UIKIT_EXTERN NSString *const UIApplicationStatusBarOrientationUserInfoKey;            // userInfo dictionary key for status bar orientation
    UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarFrameNotification;       // userInfo contains NSValue with new frame
    UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarFrameNotification;        // userInfo contains NSValue with old frame
    UIKIT_EXTERN NSString *const UIApplicationStatusBarFrameUserInfoKey;                  // userInfo dictionary key for status bar frame
    UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsURLKey                NS_AVAILABLE_IOS(3_0); // userInfo contains NSURL with launch URL
    UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsSourceApplicationKey  NS_AVAILABLE_IOS(3_0); // userInfo contains NSString with launch app bundle ID
    UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsRemoteNotificationKey NS_AVAILABLE_IOS(3_0); // userInfo contains NSDictionary with payload
    UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocalNotificationKey  NS_AVAILABLE_IOS(4_0); // userInfo contains a UILocalNotification
    UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsAnnotationKey         NS_AVAILABLE_IOS(3_2); // userInfo contains object with annotation property list
    UIKIT_EXTERN NSString *const UIApplicationProtectedDataWillBecomeUnavailable NS_AVAILABLE_IOS(4_0);
    UIKIT_EXTERN NSString *const UIApplicationProtectedDataDidBecomeAvailable    NS_AVAILABLE_IOS(4_0);
    UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocationKey           NS_AVAILABLE_IOS(4_0); // app was launched in response to a CoreLocation event.
    UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsNewsstandDownloadsKey NS_AVAILABLE_IOS(5_0); // userInfo contains an NSArray of NKAssetDownlo
    

    A few things I do to clear the deck before debugging something an odd crash.

    Build Clean (gets rid of local cached files).

    Delete the app from Simulator / Device (sometimes XIBs are cached).

    Re launch Xcode (there are some weird bugs when Xcode isn’t in sync with the current setup).

    Then, try again.