Diff
Modified: trunk/Source/WebKit/ChangeLog (251576 => 251577)
--- trunk/Source/WebKit/ChangeLog 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/ChangeLog 2019-10-25 01:07:08 UTC (rev 251577)
@@ -1,3 +1,64 @@
+2019-10-24 Chris Dumez <cdu...@apple.com>
+
+ Simplify ProcessThrottler implementation
+ https://bugs.webkit.org/show_bug.cgi?id=203370
+
+ Reviewed by Alex Christensen.
+
+ Simplify ProcessThrottler implementation by:
+ - Getting rid of CancelPrepareToSuspend IPC. Instead a regular ProcessDidResume IPC is sent to
+ the child process.
+ - Getting rid of the ProcessWillSuspendImminently IPC and send a regular ProcessDidResume IPC
+ with a 'isSuspensionImminent' flag instead.
+ - Whether the suspension is imminent or not, the child process now always responds with
+ a ProcessReadyToSuspend IPC. This simplifies our logic as the idea is that treating imminent
+ and non-imminent suspension should share as much of the same logic as possible.
+ - All PrepareToSuspend IPCs now have an associated identifier and the child process sends back
+ this identifier when responding with a ProcessReadyToSuspend IPC. This allows the
+ ProcessThrottler to easily ignore outdated requests to suspend, without requiring the
+ m_suspendMessageCount data member we had.
+
+ This patch also adds more logging to ProcessThrottler and the suspension logic in the child
+ processes. All ProcessThrottler logging now also shows the child process's PID for clarity.
+
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::processWillSuspendImminentlyForTestingSync):
+ (WebKit::NetworkProcess::prepareToSuspend):
+ * NetworkProcess/NetworkProcess.h:
+ * NetworkProcess/NetworkProcess.messages.in:
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView _processWillSuspendImminentlyForTesting]):
+ * UIProcess/Network/NetworkProcessProxy.cpp:
+ (WebKit::NetworkProcessProxy::sendPrepareToSuspend):
+ (WebKit::NetworkProcessProxy::processReadyToSuspend):
+ * UIProcess/Network/NetworkProcessProxy.h:
+ * UIProcess/Network/NetworkProcessProxy.messages.in:
+ * UIProcess/ProcessThrottler.cpp:
+ (WebKit::generatePrepareToSuspendRequestID):
+ (WebKit::ProcessThrottler::ProcessThrottler):
+ (WebKit::m_backgroundCounter):
+ (WebKit::ProcessThrottler::expectedAssertionState):
+ (WebKit::ProcessThrottler::updateAssertionStateNow):
+ (WebKit::ProcessThrottler::setAssertionState):
+ (WebKit::ProcessThrottler::updateAssertionIfNeeded):
+ (WebKit::ProcessThrottler::didConnectToProcess):
+ (WebKit::ProcessThrottler::prepareToSuspendTimeoutTimerFired):
+ (WebKit::ProcessThrottler::processReadyToSuspend):
+ (WebKit::ProcessThrottler::clearPendingRequestToSuspend):
+ (WebKit::ProcessThrottler::sendPrepareToSuspendIPC):
+ (WebKit::ProcessThrottler::uiAssertionWillExpireImminently):
+ * UIProcess/ProcessThrottler.h:
+ * UIProcess/ProcessThrottlerClient.h:
+ * UIProcess/WebProcessProxy.cpp:
+ (WebKit::WebProcessProxy::sendPrepareToSuspend):
+ (WebKit::WebProcessProxy::processReadyToSuspend):
+ * UIProcess/WebProcessProxy.h:
+ * UIProcess/WebProcessProxy.messages.in:
+ * WebProcess/WebProcess.cpp:
+ (WebKit::WebProcess::prepareToSuspend):
+ * WebProcess/WebProcess.h:
+ * WebProcess/WebProcess.messages.in:
+
2019-10-23 Ryosuke Niwa <rn...@webkit.org>
Add a mechanism to find and manipulate text by paragraphs
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (251576 => 251577)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-10-25 01:07:08 UTC (rev 251577)
@@ -2075,8 +2075,21 @@
platformProcessDidTransitionToBackground();
}
-void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
+void NetworkProcess::processWillSuspendImminentlyForTestingSync(CompletionHandler<void()>&& completionHandler)
{
+ prepareToSuspend(0, true);
+ completionHandler();
+}
+
+void NetworkProcess::prepareToSuspend(uint64_t requestToSuspendID, bool isSuspensionImminent)
+{
+ RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend(%" PRIu64 "), isSuspensionImminent: %d", this, requestToSuspendID, isSuspensionImminent);
+
+#if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
+ for (auto& server : m_idbServers.values())
+ server->tryStop(isSuspensionImminent ? IDBServer::ShouldForceStop::Yes : IDBServer::ShouldForceStop::No);
+#endif
+
#if PLATFORM(IOS_FAMILY)
m_webSQLiteDatabaseTracker.setIsSuspended(true);
#endif
@@ -2084,11 +2097,11 @@
lowMemoryHandler(Critical::Yes);
RefPtr<CallbackAggregator> callbackAggregator;
- if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
- callbackAggregator = CallbackAggregator::create([this] {
- RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
+ if (requestToSuspendID) {
+ callbackAggregator = CallbackAggregator::create([this, requestToSuspendID] {
+ RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend(%" PRIu64 ") Sending ProcessReadyToSuspend IPC message", this, requestToSuspendID);
if (parentProcessConnection())
- parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
+ parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(requestToSuspendID), 0);
});
}
@@ -2108,44 +2121,6 @@
m_storageManagerSet->suspend([callbackAggregator] { });
}
-void NetworkProcess::processWillSuspendImminently()
-{
- RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() BEGIN", this);
-#if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
- for (auto& server : m_idbServers.values())
- server->tryStop(IDBServer::ShouldForceStop::Yes);
-#endif
- actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
- RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() END", this);
-}
-
-void NetworkProcess::processWillSuspendImminentlyForTestingSync(CompletionHandler<void()>&& completionHandler)
-{
- processWillSuspendImminently();
- completionHandler();
-}
-
-void NetworkProcess::prepareToSuspend()
-{
- RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
-
-#if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
- for (auto& server : m_idbServers.values())
- server->tryStop(IDBServer::ShouldForceStop::No);
-#endif
- actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
-}
-
-void NetworkProcess::cancelPrepareToSuspend()
-{
- // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
- // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
- // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
- // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
- RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
- resume();
-}
-
void NetworkProcess::applicationDidEnterBackground()
{
m_downloadManager.applicationDidEnterBackground();
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (251576 => 251577)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-10-25 01:07:08 UTC (rev 251577)
@@ -174,10 +174,8 @@
void ensureSession(const PAL::SessionID&, bool shouldUseTestingNetworkSession, const String& identifier);
#endif
- void processWillSuspendImminently();
void processWillSuspendImminentlyForTestingSync(CompletionHandler<void()>&&);
- void prepareToSuspend();
- void cancelPrepareToSuspend();
+ void prepareToSuspend(uint64_t requestToSuspendID, bool isSuspensionImminent);
void processDidResume();
void resume();
@@ -357,8 +355,6 @@
void platformProcessDidTransitionToForeground();
void platformProcessDidTransitionToBackground();
- enum class ShouldAcknowledgeWhenReadyToSuspend { No, Yes };
- void actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend);
void platformPrepareToSuspend(CompletionHandler<void()>&&);
void platformProcessDidResume();
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (251576 => 251577)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in 2019-10-25 01:07:08 UTC (rev 251577)
@@ -74,10 +74,8 @@
ProcessDidTransitionToBackground()
ProcessDidTransitionToForeground()
- ProcessWillSuspendImminently()
ProcessWillSuspendImminentlyForTestingSync() -> () Synchronous
- PrepareToSuspend()
- CancelPrepareToSuspend()
+ PrepareToSuspend(uint64_t requestToSuspendID, bool isSuspensionImminent)
ProcessDidResume()
#if ENABLE(RESOURCE_LOAD_STATISTICS)
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2019-10-25 01:07:08 UTC (rev 251577)
@@ -7611,7 +7611,7 @@
- (void)_processWillSuspendImminentlyForTesting
{
if (_page)
- _page->process().sendProcessWillSuspendImminently();
+ _page->process().sendPrepareToSuspend(0, WebKit::IsSuspensionImminent::Yes);
}
- (void)_processDidResumeForTesting
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-10-25 01:07:08 UTC (rev 251577)
@@ -1068,12 +1068,6 @@
}
#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
-void NetworkProcessProxy::sendProcessWillSuspendImminently()
-{
- if (canSendMessage())
- send(Messages::NetworkProcess::ProcessWillSuspendImminently(), 0);
-}
-
void NetworkProcessProxy::sendProcessWillSuspendImminentlyForTesting()
{
if (canSendMessage())
@@ -1080,18 +1074,12 @@
sendSync(Messages::NetworkProcess::ProcessWillSuspendImminentlyForTestingSync(), Messages::NetworkProcess::ProcessWillSuspendImminentlyForTestingSync::Reply(), 0);
}
-void NetworkProcessProxy::sendPrepareToSuspend()
+void NetworkProcessProxy::sendPrepareToSuspend(uint64_t requestToSuspendID, IsSuspensionImminent isSuspensionImminent)
{
if (canSendMessage())
- send(Messages::NetworkProcess::PrepareToSuspend(), 0);
+ send(Messages::NetworkProcess::PrepareToSuspend(requestToSuspendID, isSuspensionImminent == IsSuspensionImminent::Yes), 0);
}
-void NetworkProcessProxy::sendCancelPrepareToSuspend()
-{
- if (canSendMessage())
- send(Messages::NetworkProcess::CancelPrepareToSuspend(), 0);
-}
-
void NetworkProcessProxy::sendProcessDidResume()
{
if (canSendMessage())
@@ -1098,9 +1086,9 @@
send(Messages::NetworkProcess::ProcessDidResume(), 0);
}
-void NetworkProcessProxy::processReadyToSuspend()
+void NetworkProcessProxy::processReadyToSuspend(uint64_t requestToSuspendID)
{
- m_throttler.processReadyToSuspend();
+ m_throttler.processReadyToSuspend(requestToSuspendID);
}
void NetworkProcessProxy::didSetAssertionState(AssertionState)
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-10-25 01:07:08 UTC (rev 251577)
@@ -160,7 +160,7 @@
void setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID, bool, CompletionHandler<void()>&&);
#endif
- void processReadyToSuspend();
+ void processReadyToSuspend(uint64_t requestToSuspendID);
void sendProcessDidTransitionToForeground();
void sendProcessDidTransitionToBackground();
@@ -191,7 +191,6 @@
#endif
// ProcessThrottlerClient
- void sendProcessWillSuspendImminently() final;
void sendProcessDidResume() final;
void sendProcessWillSuspendImminentlyForTesting();
@@ -209,8 +208,7 @@
void clearCallbackStates();
// ProcessThrottlerClient
- void sendPrepareToSuspend() final;
- void sendCancelPrepareToSuspend() final;
+ void sendPrepareToSuspend(uint64_t requestToSuspendID, IsSuspensionImminent) final;
void didSetAssertionState(AssertionState) final;
// IPC::Connection::Client
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in 2019-10-25 01:07:08 UTC (rev 251577)
@@ -31,7 +31,7 @@
TestProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebKit::WebPageProxyIdentifier pageID) -> (bool handled) Synchronous
- ProcessReadyToSuspend()
+ ProcessReadyToSuspend(uint64_t pendingRequestToSuspendID)
SetIsHoldingLockedFiles(bool isHoldingLockedFiles)
# Diagnostic messages logging
Modified: trunk/Source/WebKit/UIProcess/ProcessThrottler.cpp (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/ProcessThrottler.cpp 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/ProcessThrottler.cpp 2019-10-25 01:07:08 UTC (rev 251577)
@@ -31,21 +31,25 @@
namespace WebKit {
-static const Seconds processSuspensionTimeout { 30_s };
-
+static const Seconds processSuspensionTimeout { 20_s };
+
+static uint64_t generatePrepareToSuspendRequestID()
+{
+ static uint64_t prepareToSuspendRequestID = 0;
+ return ++prepareToSuspendRequestID;
+}
+
ProcessThrottler::ProcessThrottler(ProcessThrottlerClient& process, bool shouldTakeUIBackgroundAssertion)
: m_process(process)
- , m_suspendTimer(RunLoop::main(), this, &ProcessThrottler::suspendTimerFired)
- , m_foregroundCounter([this](RefCounterEvent) { updateAssertion(); })
- , m_backgroundCounter([this](RefCounterEvent) { updateAssertion(); })
+ , m_prepareToSuspendTimeoutTimer(RunLoop::main(), this, &ProcessThrottler::prepareToSuspendTimeoutTimerFired)
+ , m_foregroundCounter([this](RefCounterEvent) { updateAssertionIfNeeded(); })
+ , m_backgroundCounter([this](RefCounterEvent) { updateAssertionIfNeeded(); })
, m_shouldTakeUIBackgroundAssertion(shouldTakeUIBackgroundAssertion)
{
}
-AssertionState ProcessThrottler::assertionState()
+AssertionState ProcessThrottler::expectedAssertionState()
{
- ASSERT(!m_suspendTimer.isActive());
-
if (m_foregroundCounter.value())
return AssertionState::Foreground;
if (m_backgroundCounter.value())
@@ -53,86 +57,112 @@
return AssertionState::Suspended;
}
-void ProcessThrottler::updateAssertionNow()
+void ProcessThrottler::updateAssertionStateNow()
{
- m_suspendTimer.stop();
- if (m_assertion) {
- auto newState = assertionState();
- if (m_assertion->state() == newState)
- return;
- RELEASE_LOG(ProcessSuspension, "%p - ProcessThrottler::updateAssertionNow() updating process assertion state to %u (foregroundActivities: %lu, backgroundActivities: %lu)", this, newState, m_foregroundCounter.value(), m_backgroundCounter.value());
- m_assertion->setState(newState);
- m_process.didSetAssertionState(newState);
- }
+ setAssertionState(expectedAssertionState());
}
+
+void ProcessThrottler::setAssertionState(AssertionState newState)
+{
+ RELEASE_ASSERT(m_assertion);
+ if (m_assertion->state() == newState)
+ return;
+
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::setAssertionState() Updating process assertion state to %u (foregroundActivities: %lu, backgroundActivities: %lu)", m_processIdentifier, this, newState, m_foregroundCounter.value(), m_backgroundCounter.value());
+ m_assertion->setState(newState);
+ m_process.didSetAssertionState(newState);
+}
-void ProcessThrottler::updateAssertion()
+void ProcessThrottler::updateAssertionIfNeeded()
{
- bool shouldBeRunnable = this->shouldBeRunnable();
-
- // If the process is currently runnable but will be suspended then first give it a chance to complete what it was doing
- // and clean up - move it to the background and send it a message to notify. Schedule a timeout so it can't stay running
- // in the background for too long.
- if (m_assertion && m_assertion->state() != AssertionState::Suspended && !shouldBeRunnable) {
- ++m_suspendMessageCount;
- RELEASE_LOG(ProcessSuspension, "%p - ProcessThrottler::updateAssertion() sending PrepareToSuspend IPC", this);
- m_process.sendPrepareToSuspend();
- m_suspendTimer.startOneShot(processSuspensionTimeout);
- m_assertion->setState(AssertionState::Background);
- m_process.didSetAssertionState(AssertionState::Background);
+ if (!m_assertion)
return;
- }
- if (shouldBeRunnable) {
- // If we're currently waiting for the Web process to do suspension cleanup, but no longer need to be suspended, tell the Web process to cancel the cleanup.
- if (m_suspendTimer.isActive())
- m_process.sendCancelPrepareToSuspend();
-
- if ((m_assertion && m_assertion->state() == AssertionState::Suspended) || m_uiAssertionExpired) {
+ if (shouldBeRunnable()) {
+ if (m_assertion->state() == AssertionState::Suspended || m_pendingRequestToSuspendID) {
+ if (m_assertion->state() == AssertionState::Suspended)
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::updateAssertionIfNeeded() sending ProcessDidResume IPC because the process was suspended", m_processIdentifier, this);
+ else
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::updateAssertionIfNeeded() sending ProcessDidResume IPC because the WebProcess is still processing request to suspend: %" PRIu64, m_processIdentifier, this, *m_pendingRequestToSuspendID);
m_process.sendProcessDidResume();
- m_uiAssertionExpired = false;
+ clearPendingRequestToSuspend();
}
+ } else {
+ // If the process is currently runnable but will be suspended then first give it a chance to complete what it was doing
+ // and clean up - move it to the background and send it a message to notify. Schedule a timeout so it can't stay running
+ // in the background for too long.
+ if (m_assertion->state() != AssertionState::Suspended) {
+ sendPrepareToSuspendIPC(IsSuspensionImminent::No);
+ m_prepareToSuspendTimeoutTimer.startOneShot(processSuspensionTimeout);
+ return;
+ }
}
- updateAssertionNow();
+ updateAssertionStateNow();
}
void ProcessThrottler::didConnectToProcess(ProcessID pid)
{
- RELEASE_LOG(ProcessSuspension, "%p - ProcessThrottler::didConnectToProcess(%d)", this, pid);
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::didConnectToProcess()", pid, this);
+ RELEASE_ASSERT(!m_assertion);
- m_suspendTimer.stop();
if (m_shouldTakeUIBackgroundAssertion)
- m_assertion = makeUnique<ProcessAndUIAssertion>(pid, "Web content visibility"_s, assertionState());
+ m_assertion = makeUnique<ProcessAndUIAssertion>(pid, "Web content visibility"_s, expectedAssertionState());
else
- m_assertion = makeUnique<ProcessAssertion>(pid, "Web content visibility"_s, assertionState());
- m_process.didSetAssertionState(assertionState());
+ m_assertion = makeUnique<ProcessAssertion>(pid, "Web content visibility"_s, expectedAssertionState());
+
+ m_processIdentifier = pid;
+ m_process.didSetAssertionState(expectedAssertionState());
m_assertion->setClient(*this);
}
-void ProcessThrottler::suspendTimerFired()
+void ProcessThrottler::prepareToSuspendTimeoutTimerFired()
{
- updateAssertionNow();
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::prepareToSuspendTimeoutTimerFired() Updating process assertion to allow suspension", m_processIdentifier, this);
+ RELEASE_ASSERT(m_pendingRequestToSuspendID);
+ updateAssertionStateNow();
}
-void ProcessThrottler::processReadyToSuspend()
+void ProcessThrottler::processReadyToSuspend(uint64_t requestToSuspendID)
{
- if (!--m_suspendMessageCount)
- updateAssertionNow();
- ASSERT(m_suspendMessageCount >= 0);
+ RELEASE_ASSERT(requestToSuspendID);
+ if (!m_pendingRequestToSuspendID || *m_pendingRequestToSuspendID != requestToSuspendID)
+ return;
+
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::processReadyToSuspend(%" PRIu64 ") Updating process assertion to allow suspension", m_processIdentifier, this, requestToSuspendID);
+ clearPendingRequestToSuspend();
+
+ if (m_assertion->state() != AssertionState::Suspended)
+ updateAssertionStateNow();
}
-void ProcessThrottler::didCancelProcessSuspension()
+void ProcessThrottler::clearPendingRequestToSuspend()
{
- if (!--m_suspendMessageCount)
- updateAssertionNow();
- ASSERT(m_suspendMessageCount >= 0);
+ m_prepareToSuspendTimeoutTimer.stop();
+ m_pendingRequestToSuspendID = WTF::nullopt;
}
+void ProcessThrottler::sendPrepareToSuspendIPC(IsSuspensionImminent isSuspensionImminent)
+{
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::sendPrepareToSuspendIPC() isSuspensionImminent: %d", m_processIdentifier, this, isSuspensionImminent == IsSuspensionImminent::Yes);
+ if (m_pendingRequestToSuspendID) {
+ // Do not send a new PrepareToSuspend IPC for imminent suspension if we've already sent a non-imminent PrepareToSuspend IPC.
+ RELEASE_ASSERT(isSuspensionImminent == IsSuspensionImminent::Yes);
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::sendPrepareToSuspendIPC() Not sending PrepareToSuspend() IPC because there is already one in flight (%" PRIu64 ")", m_processIdentifier, this, *m_pendingRequestToSuspendID);
+ } else {
+ m_pendingRequestToSuspendID = generatePrepareToSuspendRequestID();
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::sendPrepareToSuspendIPC() Sending PrepareToSuspend(%" PRIu64 ", isSuspensionImminent: %d) IPC", m_processIdentifier, this, *m_pendingRequestToSuspendID, isSuspensionImminent == IsSuspensionImminent::Yes);
+ m_process.sendPrepareToSuspend(*m_pendingRequestToSuspendID, isSuspensionImminent);
+ }
+
+ setAssertionState(isSuspensionImminent == IsSuspensionImminent::Yes ? AssertionState::Suspended : AssertionState::Background);
+}
+
void ProcessThrottler::uiAssertionWillExpireImminently()
{
- m_process.sendProcessWillSuspendImminently();
- m_uiAssertionExpired = true;
+ RELEASE_LOG(ProcessSuspension, "[PID: %d] %p - ProcessThrottler::uiAssertionWillExpireImminently()", m_processIdentifier, this);
+ sendPrepareToSuspendIPC(IsSuspensionImminent::Yes);
+ m_prepareToSuspendTimeoutTimer.stop();
}
-}
+} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/ProcessThrottler.h (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/ProcessThrottler.h 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/ProcessThrottler.h 2019-10-25 01:07:08 UTC (rev 251577)
@@ -41,6 +41,8 @@
typedef RefCounter<ProcessSuppressionDisabledCounterType> ProcessSuppressionDisabledCounter;
typedef ProcessSuppressionDisabledCounter::Token ProcessSuppressionDisabledToken;
+enum class IsSuspensionImminent : bool { No, Yes };
+
class ProcessThrottlerClient;
class ProcessThrottler : private ProcessAssertion::Client {
@@ -54,31 +56,34 @@
ProcessThrottler(ProcessThrottlerClient&, bool shouldTakeUIBackgroundAssertion);
- inline ForegroundActivityToken foregroundActivityToken() const;
- inline BackgroundActivityToken backgroundActivityToken() const;
+ ForegroundActivityToken foregroundActivityToken() const;
+ BackgroundActivityToken backgroundActivityToken() const;
void didConnectToProcess(ProcessID);
- void processReadyToSuspend();
- void didCancelProcessSuspension();
+ void processReadyToSuspend(uint64_t pendingRequestToSuspendID);
bool shouldBeRunnable() const { return m_foregroundCounter.value() || m_backgroundCounter.value(); }
private:
- AssertionState assertionState();
- void updateAssertion();
- void updateAssertionNow();
- void suspendTimerFired();
+ AssertionState expectedAssertionState();
+ void updateAssertionIfNeeded();
+ void updateAssertionStateNow();
+ void setAssertionState(AssertionState);
+ void prepareToSuspendTimeoutTimerFired();
+ void sendPrepareToSuspendIPC(IsSuspensionImminent);
// ProcessAssertionClient
void uiAssertionWillExpireImminently() override;
+ void clearPendingRequestToSuspend();
+
ProcessThrottlerClient& m_process;
+ ProcessID m_processIdentifier { 0 };
std::unique_ptr<ProcessAssertion> m_assertion;
- RunLoop::Timer<ProcessThrottler> m_suspendTimer;
+ RunLoop::Timer<ProcessThrottler> m_prepareToSuspendTimeoutTimer;
ForegroundActivityCounter m_foregroundCounter;
BackgroundActivityCounter m_backgroundCounter;
- int m_suspendMessageCount { 0 };
+ Optional<uint64_t> m_pendingRequestToSuspendID;
bool m_shouldTakeUIBackgroundAssertion;
- bool m_uiAssertionExpired { false };
};
inline ProcessThrottler::ForegroundActivityToken ProcessThrottler::foregroundActivityToken() const
Modified: trunk/Source/WebKit/UIProcess/ProcessThrottlerClient.h (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/ProcessThrottlerClient.h 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/ProcessThrottlerClient.h 2019-10-25 01:07:08 UTC (rev 251577)
@@ -30,13 +30,13 @@
namespace WebKit {
+enum class IsSuspensionImminent : bool;
+
class ProcessThrottlerClient {
public:
virtual ~ProcessThrottlerClient() { }
- virtual void sendProcessWillSuspendImminently() = 0;
- virtual void sendPrepareToSuspend() = 0;
- virtual void sendCancelPrepareToSuspend() = 0;
+ virtual void sendPrepareToSuspend(uint64_t requestToSuspendID, IsSuspensionImminent) = 0;
virtual void sendProcessDidResume() = 0;
virtual void didSetAssertionState(AssertionState) = 0;
};
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2019-10-25 01:07:08 UTC (rev 251577)
@@ -1217,24 +1217,12 @@
return UserData::transform(object, Transformer());
}
-void WebProcessProxy::sendProcessWillSuspendImminently()
+void WebProcessProxy::sendPrepareToSuspend(uint64_t requestToSuspendID, IsSuspensionImminent isSuspensionImminent)
{
if (canSendMessage())
- send(Messages::WebProcess::ProcessWillSuspendImminently(), 0);
+ send(Messages::WebProcess::PrepareToSuspend(requestToSuspendID, isSuspensionImminent == IsSuspensionImminent::Yes), 0);
}
-void WebProcessProxy::sendPrepareToSuspend()
-{
- if (canSendMessage())
- send(Messages::WebProcess::PrepareToSuspend(), 0);
-}
-
-void WebProcessProxy::sendCancelPrepareToSuspend()
-{
- if (canSendMessage())
- send(Messages::WebProcess::CancelPrepareToSuspend(), 0);
-}
-
void WebProcessProxy::sendProcessDidResume()
{
if (canSendMessage())
@@ -1241,16 +1229,11 @@
send(Messages::WebProcess::ProcessDidResume(), 0);
}
-void WebProcessProxy::processReadyToSuspend()
+void WebProcessProxy::processReadyToSuspend(uint64_t requestToSuspendID)
{
- m_throttler.processReadyToSuspend();
+ m_throttler.processReadyToSuspend(requestToSuspendID);
}
-void WebProcessProxy::didCancelProcessSuspension()
-{
- m_throttler.didCancelProcessSuspension();
-}
-
void WebProcessProxy::didSetAssertionState(AssertionState state)
{
#if PLATFORM(IOS_FAMILY)
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2019-10-25 01:07:08 UTC (rev 251577)
@@ -223,8 +223,7 @@
void windowServerConnectionStateChanged();
- void processReadyToSuspend();
- void didCancelProcessSuspension();
+ void processReadyToSuspend(uint64_t requestToSuspendID);
void setIsHoldingLockedFiles(bool);
@@ -299,9 +298,7 @@
void didStartProvisionalLoadForMainFrame(const URL&);
// ProcessThrottlerClient
- void sendProcessWillSuspendImminently() override;
- void sendPrepareToSuspend() override;
- void sendCancelPrepareToSuspend() override;
+ void sendPrepareToSuspend(uint64_t requestToSuspendID, IsSuspensionImminent) override;
void sendProcessDidResume() override;
void didSetAssertionState(AssertionState) override;
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.messages.in (251576 => 251577)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.messages.in 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.messages.in 2019-10-25 01:07:08 UTC (rev 251577)
@@ -37,8 +37,7 @@
GetPluginProcessConnection(uint64_t pluginProcessToken) -> (IPC::Attachment connectionHandle, bool supportsAsynchronousInitialization) Synchronous
#endif
GetNetworkProcessConnection() -> (struct WebKit::NetworkProcessConnectionInfo connectionInfo) Synchronous
- ProcessReadyToSuspend()
- DidCancelProcessSuspension()
+ ProcessReadyToSuspend(uint64_t requestToSuspendID)
SetIsHoldingLockedFiles(bool isHoldingLockedFiles)
Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (251576 => 251577)
--- trunk/Source/WebKit/WebProcess/WebProcess.cpp 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp 2019-10-25 01:07:08 UTC (rev 251577)
@@ -1377,16 +1377,17 @@
}
#endif
-void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
+void WebProcess::prepareToSuspend(uint64_t requestToSuspendID, bool isSuspensionImminent)
{
+ RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend(%" PRIu64 ") isSuspensionImminent: %d", this, requestToSuspendID, isSuspensionImminent);
SetForScope<bool> suspensionScope(m_isSuspending, true);
m_processIsSuspended = true;
#if PLATFORM(COCOA)
if (m_processType == ProcessType::PrewarmedWebContent) {
- if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
- RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
- parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
+ if (requestToSuspendID) {
+ RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend() Sending ProcessReadyToSuspend(%" PRIu64 ") IPC message", this, requestToSuspendID);
+ parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(requestToSuspendID), 0);
}
return;
}
@@ -1402,7 +1403,7 @@
MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
freezeAllLayerTrees();
-
+
#if PLATFORM(COCOA)
destroyRenderingResources();
#endif
@@ -1416,68 +1417,19 @@
updateFreezerStatus();
#endif
- markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend](bool success) {
+ markAllLayersVolatile([this, requestToSuspendID](bool success) {
if (success)
RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this);
else
RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Failed to mark all layers as volatile", this);
- if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
- RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
- parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
+ if (requestToSuspendID) {
+ RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend() Sending ProcessReadyToSuspend(%" PRIu64 ") IPC message", this, requestToSuspendID);
+ parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(requestToSuspendID), 0);
}
});
}
-void WebProcess::processWillSuspendImminently()
-{
- RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently() BEGIN", this);
- actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
- RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently() END", this);
-}
-
-void WebProcess::prepareToSuspend()
-{
- RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend()", this);
- actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
-}
-
-void WebProcess::cancelPrepareToSuspend()
-{
- RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend()", this);
-
- m_processIsSuspended = false;
-
-#if PLATFORM(COCOA)
- if (m_processType == ProcessType::PrewarmedWebContent)
- return;
-#endif
-
- unfreezeAllLayerTrees();
-
-#if PLATFORM(IOS_FAMILY)
- m_webSQLiteDatabaseTracker.setIsSuspended(false);
- SQLiteDatabase::setIsDatabaseOpeningForbidden(false);
- accessibilityProcessSuspendedNotification(false);
-#endif
-
-#if ENABLE(VIDEO)
- if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
- platformMediaSessionManager->processDidResume();
- resumeAllMediaBuffering();
-#endif
-
- // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
- // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
- if (!m_pageMarkingLayersAsVolatileCounter)
- return;
-
- cancelMarkAllLayersVolatile();
-
- RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this);
- parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
-}
-
void WebProcess::markAllLayersVolatile(WTF::Function<void(bool)>&& completionHandler)
{
RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile()", this);
Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (251576 => 251577)
--- trunk/Source/WebKit/WebProcess/WebProcess.h 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h 2019-10-25 01:07:08 UTC (rev 251577)
@@ -234,9 +234,7 @@
void setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds);
- void processWillSuspendImminently();
- void prepareToSuspend();
- void cancelPrepareToSuspend();
+ void prepareToSuspend(uint64_t requestToSuspendID, bool isSuspensionImminent);
void processDidResume();
void sendPrewarmInformation(const URL&);
@@ -388,9 +386,6 @@
void setInjectedBundleParameter(const String& key, const IPC::DataReference&);
void setInjectedBundleParameters(const IPC::DataReference&);
- enum class ShouldAcknowledgeWhenReadyToSuspend { No, Yes };
- void actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend);
-
bool areAllPagesSuspended() const;
void ensureAutomationSessionProxy(const String& sessionIdentifier);
Modified: trunk/Source/WebKit/WebProcess/WebProcess.messages.in (251576 => 251577)
--- trunk/Source/WebKit/WebProcess/WebProcess.messages.in 2019-10-25 01:00:46 UTC (rev 251576)
+++ trunk/Source/WebKit/WebProcess/WebProcess.messages.in 2019-10-25 01:07:08 UTC (rev 251577)
@@ -93,9 +93,7 @@
EnsureAutomationSessionProxy(String sessionIdentifier)
DestroyAutomationSessionProxy()
- ProcessWillSuspendImminently()
- PrepareToSuspend()
- CancelPrepareToSuspend()
+ PrepareToSuspend(uint64_t requestToSuspendID, bool isSuspensionImminent)
ProcessDidResume()
MainThreadPing()