Occasionally iOS 6 MKMapView crashes in initWithFr

2019-01-21 09:17发布

问题:

I've an app on the apple store and after the iOS6 update I've got hundred of crash report within MKMapView. I cannot manage to reproduce the crash on my devices. It looks like a problem with EAGLContext. We don't use OpenGL in our app but we have more than one instances of MKMapView in different controller. I've found a similar issue here iOS 6 app crashes in EAGLContext when displaying maps but they use OpenGL.

Here there is the backtrace:

Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0x1
Crashed Thread:  0

Thread 0 Crashed:
0   libGPUSupportMercury.dylib          0x00000e22 gpus_ReturnNotPermittedKillClient + 10
1   libGPUSupportMercury.dylib          0x3bccc5fb gldCreateContext + 190
2   GLEngine                            0x344c2b15 gliCreateContextWithShared + 676
3   OpenGLES                            0x0000491d -[EAGLContext initWithAPI:properties:] + 1433
4   OpenGLES                            0x000042d7 -[EAGLContext initWithAPI:sharedWithCompute:] + 143
5   VectorKit                           0x00011c81 -[VGLGPU init] + 105
6   VectorKit                           0x000d4659 __24+[VGLGPU sharedInstance]_block_invoke_0 + 49
7   libdispatch.dylib                   0x000014b7 _dispatch_client_callout + 23
8   libdispatch.dylib                   0x000073f7 dispatch_once_f$VARIANT$mp + 43
9   VectorKit                           0x00011c13 +[VGLGPU sharedInstance] + 39
10  VectorKit                           0x00001db1 -[VKMainLoop updateLinkState] + 485
11  VectorKit                           0x00001955 -[VKScreenCanvas _updateDisplayStatus:] + 109
12  UIKit                               0x0001c371 -[UIView initWithFrame:] + 129
13  VectorKit                           0x00010ca5 -[VGLScreenCanvas initWithFrame:context:] + 53
14  VectorKit                           0x00010a7d -[VKScreenCanvas initWithFrame:context:] + 57
15  VectorKit                           0x00010a3f -[VKScreenCanvas initWithFrame:] + 39
16  VectorKit                           0x000106bd -[VKMapCanvas initWithFrame:shouldRasterize:] + 65
17  VectorKit                           0x000104bb -[VKMapView initWithFrame:andGlobe:shouldRasterize:] + 647
18  MapKit                              0x0000dc95 -[MKMapView _commonInitAndEnableLoading:fromIB:] + 725
19  MapKit                              0x0000d811 -[MKMapView initWithFrame:] + 257
.....

回答1:

We were having a similar problem when user's background our app just as we're popping up a window that includes a map subview. The crash seemed to be happening due to the map using an openGL call while we're backgrounded. We had to wrap the map subview creation in a check like the following:

UIApplicationState appState = [[UIApplication sharedApplication] applicationState];
    if( (appState != UIApplicationStateBackground) && (appState != UIApplicationStateInactive))
    {
        // Do map subview initialization...
    }
    else
    {
        self.attemptedToLoadMap = YES;
    }

We saved off the bool so that if the app comes back to the foreground we can add the subview in for display.

You have to do this anytime you're manipulating the map in a way that causes a re-draw operation (e.g., adding an annotation).



回答2:

http://developer.apple.com/library/ios/#qa/qa1766/_index.html

This Technical QA address this issue



回答3:

We found the cause of this in our app so I wanted to post the solution in case it would help anyone else. Our primary view controller monitors significant location changes when it is displayed and stops monitoring when it is hidden. Some number of our users experienced an unrelated crash on this screen, which left the app monitoring. When an app has registered for significant location change updates, iOS will actually launch the app into the background if it is not running to tell it about the new location. Since our app displays a map when it first comes up, this caused a crash. Apple support confirmed with us that there is a bug on 32 bit devices running iOS 8.x that may cause a crash if a MapView (or other OpenGL context) is updated while the app is in the background.

We changed our code so that if the app is launched due to a significant location change we immediately stop monitoring and throw an exception to crash the app. This is completely invisible to the user so they do not notice the crash, and it prevents further crashes from happening.

- (void)validateLaunchWithOptions:(NSDictionary *)launchOptions
{
    if (launchOptions[@"UIApplicationLaunchOptionsLocationKey"]) {
        // the app was launched due to a significant location change, which is not valid and causes crashes
        // prevent this from happening again by disabling significant location monitoring
        CLLocationManager *locationManager = [[CLLocationManager alloc] init];
        [locationManager stopMonitoringSignificantLocationChanges];

        // intentionally crashing the app here; it is not in a good state and it needs to be prevented from
        // getting to any code that would re-enable significant location monitoring
        @throw [NSException exceptionWithName:@"com.redacted.significantLocationLaunch"
                                       reason:@"app may not be launched due to significant location changes"
                                     userInfo:@{}];
    }
}

We saw thousands of this crash but were not able to duplicate it on our test devices until we figured out the cause. If you would like to duplicate it (and also confirm the fix), @throw an exception immediately after your app starts monitoring significant location changes. After the app crashes, go take a drive. As soon as your phone switches cell towers iOS will launch the app in the background and you will get the crash. We were able to get our hands on one of our users phones and inspect the crash logs. All of the crashes happened during her commute to and from work.



回答4:

I'm facing a similar stack trace. I noticed that in the console it is giving more detail on the actual problem: you can't use the GPU while in the background. The maps with iOS 5 were tile based so I assume didn't use the GPU, but the new maps in iOS 6 use vector graphics and thus the GPU. As a result, any map work that used to be in the background no longer can be.