<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[202696] trunk/Source/WebKit2</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/202696">202696</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2016-06-30 13:17:30 -0700 (Thu, 30 Jun 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>[iOS] Process suspension is prevented for 30 seconds after closing a tab
https://bugs.webkit.org/show_bug.cgi?id=159280
<rdar://problem/27014867>
Reviewed by Gavin Barraclough.
When closing a tab, ConnectionTerminationWatchdog takes a background
assertion on behalf of the WebContent process and only releases it
after 30 seconds, allowing for the WebContent process to exit cleanly
without worrying about getting suspended too early.
However, the child process normally exits much sooner than this and
we end up holding a process assertion for no reason for a full 30
seconds anyway. This patch addresses the issue by registering an
invalidation handler with the BKSProcessAssertion and releasing our
our assertion in such case. The invalidation handler gets called
as soon as the child process exits.
* Platform/spi/ios/AssertionServicesSPI.h:
* UIProcess/ProcessAssertion.cpp:
(WebKit::ProcessAssertion::ProcessAssertion):
* UIProcess/ProcessAssertion.h:
(WebKit::ProcessAssertion::ProcessAssertion):
(WebKit::ProcessAssertion::validity):
* UIProcess/ios/ProcessAssertionIOS.mm:
(WebKit::ProcessAssertion::ProcessAssertion):
(WebKit::ProcessAssertion::~ProcessAssertion):
(WebKit::ProcessAndUIAssertion::updateRunInBackgroundCount):
(WebKit::ProcessAndUIAssertion::ProcessAndUIAssertion):
(WebKit::ProcessAssertion::setState): Deleted.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformspiiosAssertionServicesSPIh">trunk/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessProcessAssertioncpp">trunk/Source/WebKit2/UIProcess/ProcessAssertion.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessProcessAssertionh">trunk/Source/WebKit2/UIProcess/ProcessAssertion.h</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 (202695 => 202696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-06-30 19:15:15 UTC (rev 202695)
+++ trunk/Source/WebKit2/ChangeLog        2016-06-30 20:17:30 UTC (rev 202696)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2016-06-30 Chris Dumez <cdumez@apple.com>
+
+ [iOS] Process suspension is prevented for 30 seconds after closing a tab
+ https://bugs.webkit.org/show_bug.cgi?id=159280
+ <rdar://problem/27014867>
+
+ Reviewed by Gavin Barraclough.
+
+ When closing a tab, ConnectionTerminationWatchdog takes a background
+ assertion on behalf of the WebContent process and only releases it
+ after 30 seconds, allowing for the WebContent process to exit cleanly
+ without worrying about getting suspended too early.
+
+ However, the child process normally exits much sooner than this and
+ we end up holding a process assertion for no reason for a full 30
+ seconds anyway. This patch addresses the issue by registering an
+ invalidation handler with the BKSProcessAssertion and releasing our
+ our assertion in such case. The invalidation handler gets called
+ as soon as the child process exits.
+
+ * Platform/spi/ios/AssertionServicesSPI.h:
+ * UIProcess/ProcessAssertion.cpp:
+ (WebKit::ProcessAssertion::ProcessAssertion):
+ * UIProcess/ProcessAssertion.h:
+ (WebKit::ProcessAssertion::ProcessAssertion):
+ (WebKit::ProcessAssertion::validity):
+ * UIProcess/ios/ProcessAssertionIOS.mm:
+ (WebKit::ProcessAssertion::ProcessAssertion):
+ (WebKit::ProcessAssertion::~ProcessAssertion):
+ (WebKit::ProcessAndUIAssertion::updateRunInBackgroundCount):
+ (WebKit::ProcessAndUIAssertion::ProcessAndUIAssertion):
+ (WebKit::ProcessAssertion::setState): Deleted.
+
</ins><span class="cx"> 2016-06-30 Tim Horton <timothy_horton@apple.com>
</span><span class="cx">
</span><span class="cx"> Keep track of when a WKWebView is blank before the initial non-empty layout
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformspiiosAssertionServicesSPIh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h (202695 => 202696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h        2016-06-30 19:15:15 UTC (rev 202695)
+++ trunk/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h        2016-06-30 20:17:30 UTC (rev 202696)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx"> };
</span><span class="cx"> typedef uint32_t BKSProcessAssertionReason;
</span><span class="cx">
</span><ins>+typedef void (^BKSProcessAssertionInvalidationHandler)(void);
</ins><span class="cx"> typedef void (^BKSProcessAssertionAcquisitionHandler)(BOOL acquired);
</span><span class="cx">
</span><span class="cx"> @interface BKSProcessAssertion : NSObject
</span><span class="lines">@@ -80,6 +81,8 @@
</span><span class="cx"> @interface BKSProcessAssertion ()
</span><span class="cx"> @property (nonatomic, assign) BKSProcessAssertionFlags flags;
</span><span class="cx"> - (id)initWithPID:(pid_t)pid flags:(BKSProcessAssertionFlags)flags reason:(BKSProcessAssertionReason)reason name:(NSString *)name withHandler:(BKSProcessAssertionAcquisitionHandler)handler;
</span><ins>+
+@property (nonatomic, copy) BKSProcessAssertionInvalidationHandler invalidationHandler;
</ins><span class="cx"> - (void)invalidate;
</span><span class="cx"> @end
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessProcessAssertioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ProcessAssertion.cpp (202695 => 202696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ProcessAssertion.cpp        2016-06-30 19:15:15 UTC (rev 202695)
+++ trunk/Source/WebKit2/UIProcess/ProcessAssertion.cpp        2016-06-30 20:17:30 UTC (rev 202696)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx">
</span><span class="cx"> namespace WebKit {
</span><span class="cx">
</span><del>-ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState)
</del><ins>+ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState, std::function<void()>)
</ins><span class="cx"> : m_assertionState(assertionState)
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessProcessAssertionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ProcessAssertion.h (202695 => 202696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ProcessAssertion.h        2016-06-30 19:15:15 UTC (rev 202695)
+++ trunk/Source/WebKit2/UIProcess/ProcessAssertion.h        2016-06-30 20:17:30 UTC (rev 202696)
</span><span class="lines">@@ -26,6 +26,8 @@
</span><span class="cx"> #ifndef ProcessAssertion_h
</span><span class="cx"> #define ProcessAssertion_h
</span><span class="cx">
</span><ins>+#include <functional>
+
</ins><span class="cx"> #if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
</span><span class="cx"> #include <wtf/RetainPtr.h>
</span><span class="cx"> OBJC_CLASS BKSProcessAssertion;
</span><span class="lines">@@ -47,7 +49,7 @@
</span><span class="cx">
</span><span class="cx"> class ProcessAssertion {
</span><span class="cx"> public:
</span><del>- ProcessAssertion(pid_t, AssertionState);
</del><ins>+ ProcessAssertion(pid_t, AssertionState, std::function<void()> invalidationCallback = { });
</ins><span class="cx"> ~ProcessAssertion();
</span><span class="cx">
</span><span class="cx"> void setClient(ProcessAssertionClient& client) { m_client = &client; }
</span><span class="lines">@@ -56,9 +58,16 @@
</span><span class="cx"> AssertionState state() const { return m_assertionState; }
</span><span class="cx"> void setState(AssertionState);
</span><span class="cx">
</span><ins>+#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
+protected:
+ enum class Validity { No, Yes, Unset };
+ Validity validity() const { return m_validity; }
+#endif
+
</ins><span class="cx"> private:
</span><span class="cx"> #if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
</span><span class="cx"> RetainPtr<BKSProcessAssertion> m_assertion;
</span><ins>+ Validity m_validity { Validity::Unset };
</ins><span class="cx"> #endif
</span><span class="cx"> AssertionState m_assertionState;
</span><span class="cx"> ProcessAssertionClient* m_client { nullptr };
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosProcessAssertionIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm (202695 => 202696)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm        2016-06-30 19:15:15 UTC (rev 202695)
+++ trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm        2016-06-30 20:17:30 UTC (rev 202696)
</span><span class="lines">@@ -143,21 +143,28 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-ProcessAssertion::ProcessAssertion(pid_t pid, AssertionState assertionState)
</del><ins>+ProcessAssertion::ProcessAssertion(pid_t pid, AssertionState assertionState, std::function<void()> invalidationCallback)
+ : m_assertionState(assertionState)
</ins><span class="cx"> {
</span><del>- m_assertionState = assertionState;
-
</del><span class="cx"> BKSProcessAssertionAcquisitionHandler handler = ^(BOOL acquired) {
</span><span class="cx"> if (!acquired) {
</span><del>- LOG_ERROR("Unable to acquire assertion for process %d", pid);
</del><ins>+ LOG_ALWAYS_ERROR(true, "Unable to acquire assertion for process %d", pid);
</ins><span class="cx"> ASSERT_NOT_REACHED();
</span><ins>+ m_validity = Validity::No;
+ invalidationCallback();
</ins><span class="cx"> }
</span><span class="cx"> };
</span><span class="cx"> m_assertion = adoptNS([[BKSProcessAssertion alloc] initWithPID:pid flags:flagsForState(assertionState) reason:BKSProcessAssertionReasonExtension name:@"Web content visible" withHandler:handler]);
</span><ins>+ m_assertion.get().invalidationHandler = ^() {
+ m_validity = Validity::No;
+ invalidationCallback();
+ };
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ProcessAssertion::~ProcessAssertion()
</span><span class="cx"> {
</span><ins>+ m_assertion.get().invalidationHandler = nil;
+
</ins><span class="cx"> if (ProcessAssertionClient* client = this->client())
</span><span class="cx"> [[WKProcessAssertionBackgroundTaskManager shared] removeClient:*client];
</span><span class="cx"> [m_assertion invalidate];
</span><span class="lines">@@ -174,7 +181,7 @@
</span><span class="cx">
</span><span class="cx"> void ProcessAndUIAssertion::updateRunInBackgroundCount()
</span><span class="cx"> {
</span><del>- bool shouldHoldBackgroundAssertion = state() != AssertionState::Suspended;
</del><ins>+ bool shouldHoldBackgroundAssertion = validity() != Validity::No && state() != AssertionState::Suspended;
</ins><span class="cx">
</span><span class="cx"> if (shouldHoldBackgroundAssertion) {
</span><span class="cx"> if (!m_isHoldingBackgroundAssertion)
</span><span class="lines">@@ -188,7 +195,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ProcessAndUIAssertion::ProcessAndUIAssertion(pid_t pid, AssertionState assertionState)
</span><del>- : ProcessAssertion(pid, assertionState)
</del><ins>+ : ProcessAssertion(pid, assertionState, [this] { updateRunInBackgroundCount(); })
</ins><span class="cx"> {
</span><span class="cx"> updateRunInBackgroundCount();
</span><span class="cx"> }
</span><span class="lines">@@ -219,7 +226,7 @@
</span><span class="cx">
</span><span class="cx"> namespace WebKit {
</span><span class="cx">
</span><del>-ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState)
</del><ins>+ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState, std::function<void()>)
</ins><span class="cx"> : m_assertionState(assertionState)
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>