2012-07-20 4 views
7

Ich habe ein ziemlich gnarly technisches Problem und ich hoffe, dass es einige Webkit-Experten gibt. Ich arbeite an einer iOS-Anwendung für einen Client. Die meisten Anwendungen sind HTML5-Inhalte, die in UIWebView-Controllern bereitgestellt werden.Lesen iOS Webkit Absturz Stack Trace

Vor etwa einer Woche begann das QA-Team zu berichten, dass die Anwendung abstürzt. Wir haben in der letzten Woche ungefähr einen Absturzbericht pro Tag erhalten. Leider sind sie die Art von Absturz, bei dem keine klaren Schritte ermittelt werden können, die den Absturz konsistent reproduzieren. Seltsamerweise haben einige dieser Absturzberichte alte Versionen der iOS-Codebasis verwendet - Code, der seit Monaten erfolgreich ausgeführt wird, ohne dass jemand dieses Absturzverhalten bemerkt.

Allen Absturzsituationen ist gemeinsam, dass sie alle gegen ein aktualisiertes Back-End laufen, das die neueste Version der HTML-Web-App-Seiten bereitstellt. Es scheint so, als hätten wir etwas Neues auf der Serverseite getan, das etwas im iOS-Code zum Absturz bringt.

Die Absturzprotokolle sind ziemlich konsistent. Hier ist die symbolicated log: (. Die meisten Fragen, die Abstürze in der WebCore diskutieren mit einem Vorschlag beantwortet, die webview.delegate auf null in der dealloc Verfahren eingestellt Das scheint nicht unser Problem zu sein)

0 WebCore 0x33147ab0 WebCore::FrameLoader::cancelledError(WebCore::ResourceRequest const&) const + 4 
1 WebCore 0x33070fbe WebCore::ResourceLoader::init(WebCore::ResourceRequest const&) + 166 
2 WebCore 0x33070e66 WebCore::SubresourceLoader::startLoading() + 14 
3 WebCore 0x33070c4e WebCore::ResourceLoadScheduler::servePendingRequests(WebCore::ResourceLoadScheduler::HostInformation*, WebCore::ResourceLoadPriority) + 46 
4 WebCore 0x33076508 WebCore::ResourceLoadScheduler::servePendingRequests(WebCore::ResourceLoadPriority) + 36 
5 WebCore 0x32fd38c8 WebCore::ThreadTimers::sharedTimerFiredInternal() + 92 

.

Jetzt habe ich eine Theorie (über die ich in einem Moment sprechen werde), aber was ich nicht habe, ist ein klarer Beweis. Also nahm ich die Quelle von webkit.org und versuchte, genug davon zu lesen, um zu verstehen, was das WebKit zu der Zeit tat, als es abstürzte. Ich glaube nicht, dass ich die gleiche Version der WebKit-Quelle verwende wie auf den iOS-Geräten (wir haben das in 5.0.1- und 5.1.1-Geräten gesehen), die wichtigsten Methoden scheinen auf herunterladbare Ressourcen zu verweisen (wie CSS und Bilder), aber es scheint eine Null-URL zu geben, so dass wir am Ende die canceledError-Methode aufrufen.

Die FrameLoader dann tut dies:

ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const 
{ 
    ResourceError error = m_client->cancelledError(request); 
    error.setIsCancellation(true); 
    return error; 
} 

und es ist bei dieser Methode, dass die App stürzt mit:

Exception Type: EXC_BAD_ACCESS (SIGSEGV) 
Exception Codes: KERN_INVALID_ADDRESS at 0x00000008 

, die mir nahe, dass die m_client nicht gültig auf etwas zeigt.

Jetzt habe ich eine Theorie über das, was passiert, nur basierend auf Bauchgefühl und Indizien.

Unser UIWebView hat einen Delegaten, der die URLs auswertet, die in die Webansicht geladen werden. Unter bestimmten Umständen entscheiden wir neue URLs in einem separaten Viewcontroller zu starten, etwa so:

- (BOOL)webView:(UIWebView *)source shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{ 
    ... 

    if ([self.popupStrategy shouldPopupURL:[request URL] fromCurrent:[source.request URL]]) { 

     PopupTransitionViewController *popController = [self createPopupController:request]; 
     ... push it onto the navigation controller ... 

    } 
    ... 
} 

Eine der wichtigsten Bedingungen, die diese Pop-up-Strategie bewirkt während eines Cross-Domain-Link return true auftritt. Das heißt, wenn der Benutzer auf einen Link/ein Symbol klickt und das Ziel dieses Links von einer Website eines Drittanbieters gehostet wird, startet die App den neuen Inhalt in einem anderen ViewController (aus verschiedenen Gründen, einschließlich eines nativer Übergang auf domänenübergreifende Links).

Eine der serverseitigen Änderungen vor einigen Wochen ist, dass der Link href aktualisiert wurde - der Link ruft nun unseren Hauptserver auf, der eine HTTP-Weiterleitung zurücksendet und den Client an die Drittanbieter-Site sendet .

Was ich in diesem Fall sehe, ist, dass unsere popupStrategy zweimal aufgerufen wird.Beim ersten Mal wird die URL für unseren Hauptserver ausgewertet und beim zweiten Mal wird die URL des Drittanbieters ausgewertet. Im zweiten Fall teilt die Strategie dem UIWebView mit, die Anfrage in einem neuen ViewController zu laden. Ich denke, dass etwas im Webkit-Code nicht immer so ist, und durch einige Kuriositäten des Timings oder was auch immer, führt dies irgendwann zu einem Absturz.

Diese Theorie bleibt bei mir, weil sie auf einem neuen Web-Ladeverhalten basiert, das vorher in unserer Server-Code-Basis nicht existierte, was den Symptomen bequem entspricht. Mein Lesevorgang des Webkit-Codes ist der, dass Webkit in einigen der referenzierten Methoden einige spezielle Verarbeitungen ausführt, wenn er übergreifende Anfragen sieht. Aber der Crash war unmöglich zu reproduzieren, also haben wir nicht mehr viel zu tun. Aber wenn die Theorie stimmt, kenne ich eine vernünftige Lösung.

Meine Hoffnung ist, dass jemand eine gewisse Vertrautheit mit Webkit Interna hat und schlagen können:

a), wie gut diese Theorie durch die Webkit-Stack-Trace unterstützt wird?

b) Gibt es noch weitere Einsichten, die von der Stapelverfolgung, die ich erhalte, angezeigt werden?

Antwort

0

Ich habe Codeänderungen vorgenommen, die in der oben beschriebenen Theorie wurzeln. Nachdem diese Änderungen vorgenommen wurden, sah ich keine Wiederholung des Absturzes. Die ursprüngliche Theorie scheint also korrekt zu sein.

+0

Was haben Sie getan, um dieses Problem zu beheben? Genau das erleben wir gerade jetzt. – Shoerob

+0

Ich habe sichergestellt, dass der Übergang zum neuen Controller * vor * eine Weiterleitung aufgetreten ist. – bcholmes