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 <cdumez at apple.com>
+
+ [WK2][iOS] Intermittent crash in [UIApplication beginBackgroundTaskWithName] expiration handler
+ https://bugs.webkit.org/show_bug.cgi?id=159648
+ <rdar://problem/27219361>
+
+ 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 <mitz at apple.com>
</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 "AssertionServicesSPI.h"
</span><span class="cx"> #import <UIKit/UIApplication.h>
</span><span class="cx"> #import <wtf/HashSet.h>
</span><ins>+#import <wtf/RunLoop.h>
</ins><span class="cx"> #import <wtf/Vector.h>
</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(&client);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+- (void)_notifyClientsOfImminentSuspension
+{
+ ASSERT(RunLoop::isMain());
+ Vector<ProcessAssertionClient*> clientsToNotify;
+ copyToVector(_clients, clientsToNotify);
+ for (auto* client : clientsToNotify)
+ client->assertionWillExpireImminently();
+}
+
</ins><span class="cx"> - (void)_updateBackgroundTask
</span><span class="cx"> {
</span><span class="cx"> if (_needsToRunInBackgroundCount && _backgroundTask == UIBackgroundTaskInvalid) {
</span><span class="cx"> _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"com.apple.WebKit.ProcessAssertion" expirationHandler:^{
</span><del>- NSLog(@"Background task expired while holding WebKit ProcessAssertion.");
- Vector<ProcessAssertionClient*> clientsToNotify;
- copyToVector(_clients, clientsToNotify);
- for (auto* client : clientsToNotify)
- client->assertionWillExpireImminently();
</del><ins>+ LOG_ALWAYS_ERROR(true, "Background task expired while holding WebKit ProcessAssertion (isMainThread? %d).", 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