No subject


Tue May 3 15:05:30 PDT 2016


certain conditions, which our code is designed to deal with.

In particular, we get called on a non-main thread when UIKit fails to acquire the assertion.
Update our expiration handler to always notify the clients on the main thread.

* UIProcess/ios/ProcessAssertionIOS.mm:
(-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosProcessAssertionIOSmm">trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (203093 => 203094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog	2016-07-11 23:25:40 UTC (rev 203093)
+++ trunk/Source/WebKit2/ChangeLog	2016-07-11 23:29:23 UTC (rev 203094)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2016-07-11  Chris Dumez  &lt;cdumez at apple.com&gt;
+
+        [WK2][iOS] Intermittent crash in [UIApplication beginBackgroundTaskWithName] expiration handler
+        https://bugs.webkit.org/show_bug.cgi?id=159648
+        &lt;rdar://problem/27219361&gt;
+
+        Reviewed by Anders Carlsson.
+
+        We see an intermittent crash in [UIApplication beginBackgroundTaskWithName] expiration handler.
+        From the traces, we noticed the expiration handler can get called on a non-main thread under
+        certain conditions, which our code is designed to deal with.
+
+        In particular, we get called on a non-main thread when UIKit fails to acquire the assertion.
+        Update our expiration handler to always notify the clients on the main thread.
+
+        * UIProcess/ios/ProcessAssertionIOS.mm:
+        (-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):
+
</ins><span class="cx"> 2016-07-11  Dan Bernstein  &lt;mitz at apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Tried to fix the macOS build.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosProcessAssertionIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm (203093 => 203094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm	2016-07-11 23:25:40 UTC (rev 203093)
+++ trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm	2016-07-11 23:29:23 UTC (rev 203094)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #import &quot;AssertionServicesSPI.h&quot;
</span><span class="cx"> #import &lt;UIKit/UIApplication.h&gt;
</span><span class="cx"> #import &lt;wtf/HashSet.h&gt;
</span><ins>+#import &lt;wtf/RunLoop.h&gt;
</ins><span class="cx"> #import &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if !PLATFORM(IOS_SIMULATOR)
</span><span class="lines">@@ -91,15 +92,28 @@
</span><span class="cx">     _clients.remove(&amp;client);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_notifyClientsOfImminentSuspension
+{
+    ASSERT(RunLoop::isMain());
+    Vector&lt;ProcessAssertionClient*&gt; clientsToNotify;
+    copyToVector(_clients, clientsToNotify);
+    for (auto* client : clientsToNotify)
+        client-&gt;assertionWillExpireImminently();
+}
+
</ins><span class="cx"> - (void)_updateBackgroundTask
</span><span class="cx"> {
</span><span class="cx">     if (_needsToRunInBackgroundCount &amp;&amp; _backgroundTask == UIBackgroundTaskInvalid) {
</span><span class="cx">         _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@&quot;com.apple.WebKit.ProcessAssertion&quot; expirationHandler:^{
</span><del>-            NSLog(@&quot;Background task expired while holding WebKit ProcessAssertion.&quot;);
-            Vector&lt;ProcessAssertionClient*&gt; clientsToNotify;
-            copyToVector(_clients, clientsToNotify);
-            for (auto* client : clientsToNotify)
-                client-&gt;assertionWillExpireImminently();
</del><ins>+            LOG_ALWAYS_ERROR(true, &quot;Background task expired while holding WebKit ProcessAssertion (isMainThread? %d).&quot;, RunLoop::isMain());
+            // The expiration handler gets called on a non-main thread when the underlying assertion could not be taken (rdar://problem/27278419).
+            if (RunLoop::isMain())
+                [self _notifyClientsOfImminentSuspension];
+            else {
+                dispatch_sync(dispatch_get_main_queue(), ^{
+                    [self _notifyClientsOfImminentSuspension];
+                });
+            }
</ins><span class="cx">             [[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
</span><span class="cx">             _backgroundTask = UIBackgroundTaskInvalid;
</span><span class="cx">         }];
</span></span></pre>
</div>
</div>

</body>
</html>


More information about the webkit-changes mailing list