Unreproducible webcore crashes

I’ve got an iPad app that’s in the App Store for around three months now and I’ve been receiving some weird crash reports that I can’t figure out. These are not that frequent, got around 15-20 instances since the launch but still frequent enough to actually bug me. The crashes are slightly different (see stack traces below) but since they are related to WebCore I’m guessing they have to do with the usage of the UIWebView in the app and might have a common cause, though I’m not 100% positive. The deployment target of the app is iOS 6.0 but crashes appear on iPad 2, iPad 3 and iPad Mini, exclusively on iOS 7.

There is only one place in the app where I’m using a webview, for displaying news article web pages from various sources. I have one view controller for this that has a UIWebView as its view. There is one instance of this view controller that lives throughout the app, each time a new article is selected the existing webview reloads with the url of the newly selected article.

  • Swift : Use closure compatible with Objective-C block
  • How can I use Tensorflow with react-native?
  • Recording audio file using AVAudioEngine
  • iOS 7 UIWebView not rendering
  • How to clean the content of UIWebView without loading an empty page?
  • UINavigationBar background color setted from storyboard differ from the color setted by code
  • One of the proposed solutions based on the discussion around WebCore issues suggested setting the webviews delegate property to nil in the controller’s dealloc method. Unfortunately I don’t think it’s applicable in my case because the view controller does not get deallocated during the lifecycle of the app.
    Another issue might be incorrect webpages that have bad image references in the CSS (loadPendingImages crash). I couldn’t find such a page yet though.
    Also, I double-checked and made sure to do webview-related operations on the main thread.

    The crashes are

    Exception Type: EXC_BAD_ACCESS 
    Code: KERN_INVALID_ADDRESS
    

    with the following stack traces (full ones here)

    0 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 815
    1 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 788
    2 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
    3 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
    4 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
    5 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458
    

    and

    0 WebCore WebCore::StyleResolver::loadPendingImages() + 1153
    1 WebCore WebCore::ResourceRequestBase::~ResourceRequestBase() + 104
    2 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 782
    3 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
    4 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
    5 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
    

    and

    0 WebCore WebCore::StyleResolver::adjustRenderStyle(WebCore::RenderStyle*, WebCore::RenderStyle*, WebCore::Element*) + 19
    1 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 964
    2 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
    3 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
    4 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458
    5 WebCore WebCore::CSSComputedStyleDeclaration::getPropertyValue(WebCore::CSSPropertyID) const + 42
    

    and

    0 WebCore WebCore::TimerBase::heapDeleteMin() + 37
    1 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
    2 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
    3 WebCore WebCore::timerFired(__CFRunLoopTimer*, void*) + 24
    4 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
    5 CoreFoundation __CFRunLoopDoTimer + 782
    

    Has anyone experienced similar crashes? If so:
    1. Are there ways to replicate them?
    2. How can one debug these without replicating them?
    3. What fixes solved the issues?

    Thanks!

    2 Solutions Collect From Internet About “Unreproducible webcore crashes”

    I had exactly the same issue in an app I worked on, it weirdly only occurred on older devices running iOS 7. I suspect this has something to do with them not being able to keep up.

    What I had was a UITableView where one of the rows would open a UIViewController that had a UIWebView on it for custom adverts. What I found is that on the older devices objects and memory where being free’d up far more regularly than I’d seen in other platforms. I could mimic the crash very easily on an iPhone 4 by going in / out of the screen 2 or 3 times. Where as an iPhone 5 I spent 15 minutes doing the same and couldn’t fault it.

    I know you may feel like your controller is not being dealloc’d but it really sounds as though it is or some reference is being dropped, I have also seen my delegate references disappear a few times in this app also.

    My advice and what worked for me is to stop the execution of the webview and set everything to nil when you can.

    In one instance on my app I chose to do it on the viewWillDisappear callback, because in my circumstance it was gone from the user and recreated later, so I blanked everything like so:

    [webView stopLoading];
    
    self.webView.delegate = nil;
    self.webView = nil;
    

    Look at your Javascript-to-Objective-C code and if you are executing/calling javascript code make sure that script does not invoke new calls to Objective-C.

    This is proper usage:

    Javascript >> Objective-C
    
    Objective-C >> Javascript
    

    This is reason for crash:

    Objective-C >> Javascript >> Objective-C (here is possible crash depending on some race conditions)

    Solution is specific for your project code. But easiest would be to wrap all Javascript in setTimeout() to schedule execution in Javascript thread. Here is simple example, your Objective-C code needs to execute this script:

    storeUserPhoneNumber("011 123 4567");
    

    Crash will happen if storeUserPhoneNumber function calls back to Objective-C code (directly or indirectly) in its body. To fix this just wrap code in setTimeout like this:

    setTimeout(function() {
        storeUserPhoneNumber("011 123 4567");
    }, 0);