10

While testing a new build of our iPhone app, we're occasionally seeing the app window go completely black when resuming the app sometime after applicationWillEnterForeground. The only way to make the app work again is to close it completely and then restart the app. We have not been able to identify steps to consistently reproduce. This issue seems to happen at random, but only when going back into the app after it has been put in the background. Sometimes it happens after a few seconds, sometimes it won't happen for over a week.

Here are the threads in the main view during normal operation:

threadsDuringNormalOperation

Here are the threads when this issue happens and I pause the debugger:

threadsDuringBlackScreen

Things I've tried

Logging everything when the app resumes

Nothing appears to be out of order when the app resumes. Furthermore, none of my code is executed after applicationDidBecomeActive until the home button is pressed.

2013-05-15 22:22:23 AppDelegate::applicationDidBecomeActive
2013-05-15 22:22:23 self.window = <UIWindow: 0x1dd6ee80; frame = (0 0; 320 480); opaque = NO; autoresize = RM+BM; layer = <UIWindowLayer: 0x1dd6ef80>>
2013-05-15 22:22:23 self.window.subviews.count = 7
2013-05-15 22:22:23 self.navigationController = <UINavigationController: 0x1dd87190>
2013-05-15 22:22:23 self.navigationController.visibleViewController = <MyViewController: 0x1dd7ffe0>
2013-05-15 22:22:23 self.navigationController.view = <UILayoutContainerView: 0x1dd876e0; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x1dd877a0>>
2013-05-15 22:22:23 self.navigationController.viewControllers.count = 1
2013-05-15 22:22:23 TestFlight: App Token is recognized
2013-05-15 22:22:24 AppDelegate::applicationWillResignActive
2013-05-15 22:22:24 TestFlight: End of Session

There are a few items in the log that concerned me at first, but I have observed them during normal operation so I no longer think that they are related. Just in case, here they are:

Immediately following ApplicationWillEnterForeground:

installd[54] <Error>: 0x2ff8d000 filter_attributes: Info.plist keys requested via MobileInstallationLookup/Browse in client Xcode (via mobile_installation_proxy) were not found in MobileInstallation's cache. Please file a bug requesting that these keys be added: <CFBasicHash 0x1cd86080 [0x3c44d100]>{type = mutable set, count = 18,
entries =>
    0 : <CFString 0x3c4399f4 [0x3c44d100]>{contents = "CFBundlePackageType"}
    1 : <CFString 0x1cebf1e0 [0x3c44d100]>{contents = "BuildMachineOSBuild"}
    2 : <CFString 0x3c43aa44 [0x3c44d100]>{contents = "CFBundleResourceSpecification"}
    3 : <CFString 0x1ce90cf0 [0x3c44d100]>{contents = "DTPlatformBuild"}
    4 : <CFString 0x3c437794 [0x3c44d100]>{contents = "DTCompiler"}
    5 : <CFString 0x3c439564 [0x3c44d100]>{contents = "CFBundleSignature"}
    6 : <CFString 0x3c43a224 [0x3c44d100]>{contents = "DTSDKName"}
    7 : <CFString 0x1cebe5f0 [0x3c44d100]>{contents = "NSBundleResolvedPath"}
    8 : <CFString 0x3c436eb4 [0x3c44d100]>{contents = "UISupportedInterfaceOrientations"}
    10 : <CFString 0x3c43ee84 [0x3c44d100]>{contents = "DTXcode"}
    13 : <CFString 0x3c43eeb4 [0x3c44d100]>{contents = "CFBundleInfoDictionaryVersion"}
    16 : <CFString 0x3c43c304 [0x3c44d100]>{contents = "CFBundleSupportedPlatforms"}
    17 : <CFString 0x1ceabd10 [0x3c44d100]>{contents = "DTXcodeBuild"}
    18 : <CFString 0x1cebb610 [0x3c44d100]>{contents = "UIStatusBarTintParameters"}
    19 : <CFString 0x3c43ae54 [0x3c44d100]>{contents = "DTPlatformVersion"}
    20 : <CFString 0x3c43dbf4 [0x3c44d100]>{contents = "DTPlatformName"}
    21 : <CFString 0x3c43ec84 [0x3c44d100]>{contents = "CFBundleDevelopmentRegion"}
    22 : <CFString 0x1ceb9ae0 [0x3c44d100]>{contents = "DTSDKBuild"}
}

Shortly afterwards:

lockdownd[45] <Notice>: 2ff24000 special_case_get: MGCopyAnswer(kMGQReleaseType) returned NULL

Removing TestFlight

This is a build distributed via TestFlight, which we have used successfully for several previous releases. I have observed this behavior in a build deployed by Xcode as well, so that rules out TestFlight as a potential offender, at least in terms of the deployment. Furthermore, I have removed the TestFlight calls from the code and tested the application. After a few days, I observed the issue, so I know it's not related to TestFlight.

Verified that all NSURLConnections are performed asynchronously

Verified that all updating of the UI is performed on the main thread

The only pieces of information I really have at this point is that somehow main and UIApplicationMain are no longer on the stack. How can that happen?

Also, this app uses SDWebImage and there are UIImageViews in the displayed view when this issue happens, so maybe there's an issue there, but I really doubt that such a highly used library would have such a glaring flaw.

Isaac Overacker
  • 1,385
  • 10
  • 22
  • You can create a log file in your Documentation folder, and log all kinds of events that happen around going into the background and then coming back. Pull the logs from iCloud or iTunes. Iterating on this might lead you to the problem. – David H May 04 '13 at 20:29
  • @DavidH, thanks for the suggestion. Can you elaborate on this process? How is it superior to the normal Console logging that you can access through the Xcode organizer? – Isaac Overacker May 04 '13 at 20:49
  • Since this is just for debugging use appDelegate. It opens a file in the Documentation directory, and you in essence output your ASCII messages to that file then sync the file after each message. I personally have found the iOS console not as reliable but you could try that first. Thread 1 looks very bad but no ideas how that happened. You need to log everything at wake up time. – David H May 05 '13 at 12:24
  • Were you ever able to solve this and/or find the source of the black screen? I'm encountering a similar issue and hoping for any insights! – Benchtop Creative Jan 23 '14 at 02:38
  • @BenchtopCreative unfortunately, no. We have since done a major rewrite of the UI for iOS 7 and we no longer see the issue, but never did determine the cause. – Isaac Overacker Jan 23 '14 at 18:34

1 Answers1

7

This occurs when the main thread is not allowed to run to refresh the UI. Possible causes:

  • Deadlock (most common in my experience)
  • Doing synchronous network calls while on a bad network connection
  • Infinite loop

I would suggest you start with checking all code that uses GCD and other threading mechanisms.

Good luck, these are very nasty problems. Sorry I can't be more to the point because the logs you showed don't ring a bell. BTW, do you only get these things in the log when the app hangs?

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • Thanks for the suggestions. I'll look through the revision history and see if anything stands out since our last stable build. – Isaac Overacker May 04 '13 at 21:13
  • Again good luck man, I know how horrible this kind of bugs are. – meaning-matters May 04 '13 at 21:15
  • Thanks. I don't see these in the log normally, just when the issue occurs. I'll keep an eye out for them during normal operation, though. – Isaac Overacker May 04 '13 at 21:20
  • I recently observed these log entries during normal operation, so I don't think they're part of the problem anymore. – Isaac Overacker May 13 '13 at 21:12
  • I had the same problem for months. I was using AsyncSocket (the runloop-based one) which had a call to `recvfrom` that held everything up (it's a synchronous C function that reads from a socket). Using GCDAsyncSocket solved "my" problem. – Scott Berrevoets May 21 '13 at 19:57