I upload a demo project in github. And I added a branch while I am
trying to reproduce the issue. See the stack trace at the end of this
post.
This issue happens after I autorelease GADInterstitial object.
If you want to see some snippets, please clone this git repository. I
do not use timer to release object.
https://github.com/shinping/AdMob_SDK_604_crash
then git checkout this branch, adMobInterstitial603.
Do not checkout master branch. The master branch doesn't display
GADInterstitial.
>>
Here is the stack trace. I guess this project can be solved if you
look at (GADPrivateUtilities.m:43)
SDK version is 6.0.3
I can reproduce this issue once a day.
It happens on version 6.0.1 and 6.0.3. It will probably happen on
version 6.0.4. It happens more often on version 6.0.1.
But this issue doesn't happen in my short demo project.
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0xffffffff
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 CoreFoundation 0x35c73e58 CFHash + 20
1 CoreFoundation 0x35cefbe0
__CFDictionaryStandardHashKey + 16
2 CoreFoundation 0x35d40d70 __CFBasicHashRehash +
1828
3 CoreFoundation 0x35d432a8 __CFBasicHashRemoveValue
+ 516
4 CoreFoundation 0x35c777e4 CFBasicHashRemoveValue +
2900
5 CoreFoundation 0x35c76c60 CFDictionaryRemoveValue
+ 172
6 WallpapersHD 0x000db300 +[GADPrivateUtilities
removePrivateObjectForKey:] (GADPrivateUtilities.m:43)
7 WallpapersHD 0x000f70b4 -
[GADImpressionTicketGestureRecognizer dealloc]
(GADImpressionTicketGestureRecognizer.m:60)
8 libobjc.A.dylib 0x3169f16e _objc_rootRelease + 30
9 CoreFoundation 0x35c732e0 CFRelease + 88
10 CoreFoundation 0x35c806f4 -[__NSArrayI dealloc] +
96
11 libobjc.A.dylib 0x3169f16e _objc_rootRelease + 30
12 libobjc.A.dylib 0x316a0e50 objc_release + 32
13 libobjc.A.dylib 0x3169fea6 (anonymous
namespace)::AutoreleasePoolPage::pop(void*) + 218
14 libobjc.A.dylib 0x3169fdc2 _objc_autoreleasePoolPop
+ 6
15 CoreFoundation 0x35c7acf8 _CFAutoreleasePoolPop +
12
16 CoreFoundation 0x35cfd2ac __CFRunLoopRun + 1268
17 CoreFoundation 0x35c8049e CFRunLoopRunSpecific +
294
18 CoreFoundation 0x35c80366 CFRunLoopRunInMode + 98
19 GraphicsServices 0x359ff432 GSEventRunModal + 130
20 UIKit 0x3085be76 UIApplicationMain + 1074
21 WallpapersHD 0x000239d4 main (main.m:14)
22 WallpapersHD 0x00003648 start + 32
Hey, I hope there's some progress on this - you can reproduce the crash with this in a vc:
- (void)viewDidLoad
{
[super viewDidLoad];
// Bring the ad.
// Create a view of the standard size at the bottom of the screen.
// Available AdSize constants are explained in GADAdSize.h.
bannerView_ = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
// Specify the ad's "unit identifier." This is your AdMob Publisher ID.
bannerView_.adUnitID = @"somebullshit";
// Let the runtime know which UIViewController to restore after taking
// the user wherever the ad goes and add it to the view hierarchy.
bannerView_.rootViewController = self;
[self.view addSubview:bannerView_];
// Initiate a generic request to load it with an ad.
[bannerView_ loadRequest:[GADRequest request]];
// Bring the fail.
NSString *mraidString = @"\
<html>\
<script src='mraid.js'></script>\
<script>\
(function() {\
var r = Math.floor(Math.random()*1000000);\
var u = 'http://www.some.link/ad.js?rnd='+r;\
document.write('<script src='+u+'></scr'+'ipt>');\
})()\
</script>\
</html>\
";
webView_ = [[UIWebView alloc] initWithFrame:CGRectMake(200, 200, 250, 50)];
[self.view addSubview:webView_];
[webView_ loadHTMLString:mraidString baseURL:nil];
I am also experiencing this crash, and I'd like to hightlight two things I noticed with AdMob that the crash stems from.
1. AdMob is "wire tapping" every single URL request made by the client app, even the ones that do not belong to AdMob. Put a symbolic break point "-[NSURLProtocol registerClass:]", and you will see a GADMRAIDInterceptor registers itself to NSURLProtocol to get the first dibs on deciding on whether to handle every URL request with a call stack below. This means, UNLESS you register some other class to NSURLProtocol later, AdMob will always be the first one to see and analyze your URL requests before you get a chance to! My guess is that most people like me probably don't realize this until AdMob SDK crashes and starts looking into what AdMob is really doing. Would you want your URL requests, in some context, sensitive ones to be intercepted by a 3rd party SDK? Probably not.
#0 0x00df4f22 in +[NSURLProtocol registerClass:] ()
#1 0x000284eb in +[GADMRAIDInterceptor allow]
#2 0x00025c85 in -[GADJavaScriptController loadSdkConstants:]
#3 0x00e75a39 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 ()
#4 0x018b9885 in ___CFXNotificationPost_block_invoke_0 ()
#5 0x018b97a8 in _CFXNotificationPost ()
#6 0x00dba1aa in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#7 0x00014e66 in -[GADNotificationCenter postNotificationFromURL:object:]
#8 0x00014ed5 in -[GADNotificationCenter delayedPosting:]
2. Following 1, this is where the crash comes in. Since AdMob wire taps all URL requests with GADMRAIDInterceptor registered to NSURLProtocol, [GADMRAIDInterceptor canInitWithRequest:] is invoked as the first callback for every URL request. If the URL request passed into this call back is created from a javascript file named "mraid.js", AdMob bound to crash due to referencing some object already deallocated with the call stack below. If the javascript file is named something else than "mraid.js", AdMob does not crash. There is some special logic revolving around "mraid.js" when AdMob wire tap any URL request?
#4 0x00028e89 in +[GADAdURLStash viewForURL:] EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
#5 0x000287d0 in +[GADMRAIDInterceptor canInitWithRequest:]
#6 0x00df6ab8 in +[NSURLProtocol(NSURLProtocolPrivate) _protocolClassForRequest:allowCF:] ()
#7 0x00df6dcd in nsProtCanHandleRequest ()
#8 0x044cb261 in ImplAdaptor::_canHandleRequestCallback(_CFURLRequest const*, void const*) ()
#9 0x044cb0fe in URLProtocolRegistry::findProtocolImplForRequestAndSetIntoRequest(_CFURLRequest const*) ()
#10 0x044cd2f0 in URLProtocolRegistry::bindImplementationForFoundation(_CFURLRequest const*) ()
#11 0x044cd2c8 in _CFURLProtocolBindImplementationForFoundation ()
#12 0x00df8aff in createCFRequest ()
#13 0x00eb54f2 in -[NSURLConnectionInternalConnection initWithInfo:] ()
#14 0x00eb40af in -[NSURLConnection(Private) _initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:] ()
#15 0x00eb41f6 in -[NSURLConnection initWithRequest:delegate:] ()
#16 0x00eb417b in +[NSURLConnection connectionWithRequest:delegate:] ()
The crash can be easily produced with these steps:
1. Add any javascript named "mraid.js" to your project. Make sure it appears in "Copy bundle resource" in your target.
2. Load an AdMob banner ad. After AdMob register its class to NSURLProtocol to intercept all URL, create a URL with the javascript file, and issue a request with this URL.
This is my simple view controller code to illustrate the crash by loading an AdMob banner view, tapping the home button, and going back to the app.
#import "ViewController.h"
#import "GADBannerView.h"
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
GADBannerView *bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
bannerView.adUnitID = @"replace with your AdUnitID";
bannerView.rootViewController = self;
GADRequest *request = [[GADRequest alloc] init];
[bannerView loadRequest:request];
[self.view addSubview:bannerView];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (void)doSomething:(id)sender {
// Get my mraid javascript
NSString* myMraidPath = [[NSBundle mainBundle] pathForResource:@"mraid" ofType:@"js"];
// Create my URL with my javascript
NSURL *myURL = [NSURL fileURLWithPath:myMraidPath];
// Create and issue my URL request
NSURLRequest *myURLRequest = [NSURLRequest requestWithURL:myURL];
[NSURLConnection connectionWithRequest:myURLRequest delegate:self];
--
What appears to be happening is while firing a few simultaneous async NSURLRequests, we occasionally get a crash when we're also trying to load an ad through AdMob. We believe the cause of this to be AdMob registering GADMRAIDInterceptor to NSURLProtocol while another thread is enumerating the Protocols.
We are running AdMob iOS SDK 6.1.4, and experiencing this on iOS 6.0 on iPad 2 and the new iPad.
Here's the console message from the crash:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x1e57fcb0> was mutated while being enumerated.'
and the crash log:
Thread 14 Crashed:
0 libsystem_kernel.dylib 0x3a52d350 __pthread_kill + 8
1 libsystem_c.dylib 0x35a7a11e pthread_kill + 54
2 libsystem_c.dylib 0x35ab696e abort + 90
3 libc++abi.dylib 0x36b6fd4a abort_message + 70
4 libc++abi.dylib 0x36b6cff4 default_terminate() + 20
5 libobjc.A.dylib 0x3a404a74 _objc_terminate() + 144
6 libc++abi.dylib 0x36b6d078 safe_handler_caller(void (*)()) + 76
7 libc++abi.dylib 0x36b6d110 std::terminate() + 16
8 libc++abi.dylib 0x36b6e50e __cxa_throw + 118
9 libobjc.A.dylib 0x3a4049ba objc_exception_throw + 90
10 CoreFoundation 0x384ccd80 __NSFastEnumerationMutationHandler + 124
11 Foundation 0x3623e358 +[NSURLProtocol(NSURLProtocolPrivate) _protocolClassForRequest:allowCF:] + 168
12 Foundation 0x3623e276 nsProtCanHandleRequest + 182
13 CFNetwork 0x3812839c ImplAdaptor::_canHandleRequestCallback(_CFURLRequest const*, void const*) + 20
14 CFNetwork 0x381282e0 URLProtocolRegistry::findProtocolImplForRequestAndSetIntoRequest(_CFURLRequest const*) + 72
15 CFNetwork 0x38174b90 URLProtocolRegistry::newProtocolForRequest(__CFAllocator const*, _CFURLRequest const*, URLProtocolClient*) + 16
16 CFNetwork 0x3819fcae URLConnectionLoader::ensureLoaderHasProtocolNoLock(_CFURLRequest const*) + 338
17 CFNetwork 0x381a0072 URLConnectionLoader::createProtocolAndCopyCanonicalRequestBeforeLoadHasStarted(_CFURLRequest const*) + 6
18 CFNetwork 0x3819b170 URLConnectionClient::_internalEvent_WillSendRequest() + 52
19 CFNetwork 0x38173900 __start_block_invoke_0 + 36
20 CFNetwork 0x381742f0 ___withClientAsync_block_invoke_0 + 20
21 CFNetwork 0x3819a5b6 ___withWorkQueueAsync_block_invoke_0 + 10
22 CFNetwork 0x381c4f9c ___performAsync_block_invoke_0 + 24
23 libdispatch.dylib 0x35cec11c _dispatch_call_block_and_release + 8
24 libdispatch.dylib 0x35cefeca _dispatch_queue_drain$VARIANT$mp + 138
25 libdispatch.dylib 0x35cefdbc _dispatch_queue_invoke$VARIANT$mp + 36
26 libdispatch.dylib 0x35cf091a _dispatch_root_queue_drain + 182
27 libdispatch.dylib 0x35cf0abc _dispatch_worker_thread2 + 80
28 libsystem_c.dylib 0x35a51a0e _pthread_wqthread + 358
29 libsystem_c.dylib 0x35a518a0 start_wqthread + 4
--
--
----- Original Message -----From: Todd HussSent: Friday, October 05, 2012 8:09 AMSubject: Re: gives me EXC_BAD_ACCESSWe gets lots of these crashes in our app too, would be great if google would fix this!
--
I also saw a lot of this crash.
I cannot reproduce this issue consistently. It happens rarely.
It crash when I restart the app. I was making requests that are not related to AdMob.
I saw this issue on iOS 6 iPhone device and simulator.
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0xa471140> was mutated while being enumerated.'
(lldb) po 0xa471140
(int) $1 = 172429632 <__NSArrayM 0xa471140>(
GADMRAIDInterceptor,
NSAboutURLProtocol,
NSCFURLProtocol
)
I was using AdMob SDK version 6.2.0.
--
--
Hi All,I've filed a bug with Apple about the underlying crash; it's Radar #12556160.I've also got a workaround in the meantime. Just stick the code below into a .m file and include it in your project; it will automatically run at startup and prevent NSURLProtocol classes from being unregistered or registered repeatedly. This dramatically reduces the chance of a crash. In my brief testing, it doesn't seem to cause any bad side-effects, but YMMV. I'd love to hear if anyone else finds any problems with this.Cheers,Jesse/** Begin NSURLProtocol Mutation Fix* This ensures that a class is only registered once with* NSURLProtocol and prevents classes from being unregistered.* This works around a crash where changing the list of protocol* handlers during an NSURLConnection causes a crash.*/#import <Foundation/Foundation.h>#import <objc/runtime.h>static NSMutableSet *registeredNSURLProtocols;@implementation NSURLProtocol (SMProtocolCrashWorkaround)+ (void)sm_unregisterClass:(Class)c {// intentionally blank; we disallow unregistration}+ (void)sm_registerClass:(Class)c {@synchronized(self) {if (!registeredNSURLProtocols) {registeredNSURLProtocols = [[NSMutableSet alloc] init];}if (![registeredNSURLProtocols containsObject:c]) {[registeredNSURLProtocols addObject:c];[self sm_registerClass:c];}}}@end__attribute__((constructor))static void preventProtocolMutationCrash() {Method unregisterMethod = class_getClassMethod([NSURLProtocol class], @selector(unregisterClass:));Method newUnregisterMethod = class_getClassMethod([NSURLProtocol class], @selector(sm_unregisterClass:));method_exchangeImplementations(unregisterMethod, newUnregisterMethod);Method registerMethod = class_getClassMethod([NSURLProtocol class], @selector(registerClass:));Method newRegisterMethod = class_getClassMethod([NSURLProtocol class], @selector(sm_registerClass:));method_exchangeImplementations(registerMethod, newRegisterMethod);}/*** End NSURLProtocol Mutation Fix ***/
On Friday, October 19, 2012 4:04:09 PM UTC-3, Jesse Rusak wrote:Hi Raj,(I sent this earlier, but it didn't seem to go through. Apologies if you get this twice.)I believe you're correct; the issue is cased by the ads SDK registering a protocol handler while an NSURLRequest is being sent. I've put up a sample here https://www.dropbox.com/s/72gu971lsnzhej5/AdCrash.zip which simply makes a lot of ad requests concurrently with other NSURLRequests. It reproduces the crash reliably for me after a few seconds of waiting (with the 6.2.1 SDK). This crash is currently causing the majority of the all crashes we're seeing in the wild, so it would be great if this could be resolved quickly.Unfortunately, your solution of ensuring that the ad request goes out at a different time from other requests isn't feasible; even if we could track down every NSURLRequest in all our code (and all Apple's code, and all third-party code), we wouldn't want to prevent all network traffic for the entire time we're loading an ad, since that could take tens of seconds depending on the connection.One possible solution would be to move the call to +[NSURLProtocol registerClass] from +[GADMRAIDInterceptor allow] to, say, +[GADMRAIDInterceptor initialize] and then just use a boolean to note whether the interceptor is allowed or not. (And eliminate the call to +[NSURLProtocol unregisterClass:].) This wouldn't completely eliminate the crash but it would reduce its likelihood to almost nothing. Hopefully Apple will resolve the underlying issue, but in the meantime, it would be great if you could produce a fix such as this one.Thanks,Jesse
--
--
We're anxiously awaiting a fix too, we use a crash reporting service and this is the number 1 crash by a wide margin in our production app. It pains me when we get 1 star reviews from users saying our app is crashy when by far the majority of crashes come from the AdMob SDK.
On Sunday, November 18, 2012 7:20:49 PM UTC-8, Sean Woodhouse wrote:We're using 6.2.1 and have seen a significant number of crashes. We're about to release an update and I'm hesitant to even include the AdMob ad support with the number of crashes we're seeing. Jesse seems to have pinpointed the problem but the unregisterClass swizzle is not something we can go to production with.Any word on when a proper fix will be available?Regards
Sean.
--
Any word on a release that will fix this issue? This is by far the number one cause of crashes in our apps, and method swizzling in a production app isn't something we're prepared to consider all that seriously.
On Wednesday, December 5, 2012 12:14:05 PM UTC+11, Raj Parameswaran wrote:The next release will fix this issue and is slated for Q1 of 2013. In the meantime, is there a reason the method swizzling workaround won't cut it?
--
---
You received this message because you are subscribed to the Google Groups "Google AdMob Ads Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-admob-ads...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.