Skip to content
Permalink
Browse files
Add remainingRunningTime info to logging of PrepareToSuspend message
https://bugs.webkit.org/show_bug.cgi?id=240879

Reviewed by Chris Dumez.

Replace background timing info with remaining run time info, so we have a better idea of when the message is sent and
when it is processed. We will know if the message is handled after process resumes (since process can be suspended
before it handles the message).

* Source/WebKit/GPUProcess/GPUProcess.cpp:
(WebKit::GPUProcess::prepareToSuspend):
* Source/WebKit/GPUProcess/GPUProcess.h:
* Source/WebKit/GPUProcess/GPUProcess.messages.in:
* Source/WebKit/NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::processWillSuspendImminentlyForTestingSync):
(WebKit::NetworkProcess::prepareToSuspend):
(WebKit::NetworkProcess::applicationDidEnterBackground):
(WebKit::NetworkProcess::applicationWillEnterForeground):
(WebKit::NetworkProcess::processDidResume):
* Source/WebKit/NetworkProcess/NetworkProcess.h:
* Source/WebKit/NetworkProcess/NetworkProcess.messages.in:
* Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm:
(-[WKWebView _processWillSuspendForTesting:]):
(-[WKWebView _processWillSuspendImminentlyForTesting]):
* Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp:
(WebKit::GPUProcessProxy::sendPrepareToSuspend):
* Source/WebKit/UIProcess/GPU/GPUProcessProxy.h:
* Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendPrepareToSuspend):
* Source/WebKit/UIProcess/Network/NetworkProcessProxy.h:
* Source/WebKit/UIProcess/ProcessAssertion.cpp:
(WebKit::ProcessAssertion::remainingRunTimeInSeconds):
* Source/WebKit/UIProcess/ProcessAssertion.h:
* Source/WebKit/UIProcess/ProcessThrottler.cpp:
(WebKit::ProcessThrottler::sendPrepareToSuspendIPC):
* Source/WebKit/UIProcess/ProcessThrottlerClient.h:
* Source/WebKit/UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendPrepareToSuspend):
* Source/WebKit/UIProcess/WebProcessProxy.h:
* Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::sendNetworkProcessPrepareToSuspendForTesting):
* Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm:
(WebKit::ProcessAssertion::remainingRunTimeInSeconds):
* Source/WebKit/WebProcess/WebProcess.cpp:
(WebKit::WebProcess::prepareToSuspend):
* Source/WebKit/WebProcess/WebProcess.h:
* Source/WebKit/WebProcess/WebProcess.messages.in:

Canonical link: https://commits.webkit.org/250958@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@294802 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
szewai committed May 25, 2022
1 parent 0126f61 commit 2b4a6da6b299caf5e3dce0c22ba55ef74cc8959e
Showing 22 changed files with 59 additions and 40 deletions.
@@ -282,7 +282,7 @@ void GPUProcess::initializeGPUProcess(GPUProcessCreationParameters&& parameters)
#endif
}

void GPUProcess::prepareToSuspend(bool isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
void GPUProcess::prepareToSuspend(bool isSuspensionImminent, MonotonicTime, CompletionHandler<void()>&& completionHandler)
{
RELEASE_LOG(ProcessSuspension, "%p - GPUProcess::prepareToSuspend(), isSuspensionImminent: %d", this, isSuspensionImminent);

@@ -73,7 +73,7 @@ class GPUProcess : public AuxiliaryProcess, public ThreadSafeRefCounted<GPUProce

void removeGPUConnectionToWebProcess(GPUConnectionToWebProcess&);

void prepareToSuspend(bool isSuspensionImminent, CompletionHandler<void()>&&);
void prepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime, CompletionHandler<void()>&&);
void processDidResume();
void resume();

@@ -27,7 +27,7 @@ messages -> GPUProcess LegacyReceiver {

CreateGPUConnectionToWebProcess(WebCore::ProcessIdentifier processIdentifier, PAL::SessionID sessionID, IPC::Attachment connectionIdentifier, struct WebKit::GPUProcessConnectionParameters parameters) -> ()

PrepareToSuspend(bool isSuspensionImminent) -> ()
PrepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime) -> ()
ProcessDidResume()

AddSession(PAL::SessionID sessionID, struct WebKit::GPUProcessSessionParameters parameters)
@@ -2133,7 +2133,7 @@ void NetworkProcess::terminate()

void NetworkProcess::processWillSuspendImminentlyForTestingSync(CompletionHandler<void()>&& completionHandler)
{
prepareToSuspend(true, WTFMove(completionHandler));
prepareToSuspend(true, MonotonicTime::now(), WTFMove(completionHandler));
}

void NetworkProcess::terminateRemoteWorkerContextConnectionWhenPossible(RemoteWorkerType workerType, PAL::SessionID sessionID, const WebCore::RegistrableDomain& registrableDomain, WebCore::ProcessIdentifier processIdentifier)
@@ -2156,9 +2156,11 @@ void NetworkProcess::terminateRemoteWorkerContextConnectionWhenPossible(RemoteWo
}
}

void NetworkProcess::prepareToSuspend(bool isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
void NetworkProcess::prepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime, CompletionHandler<void()>&& completionHandler)
{
RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend(), isSuspensionImminent=%d Process is %{public}sin background", this, isSuspensionImminent, m_enterBackgroundTimestamp ? "" : "not ");
auto nowTime = MonotonicTime::now();
double remainingRunTime = estimatedSuspendTime > nowTime ? (estimatedSuspendTime - nowTime).value() : 0.0;
RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend(), isSuspensionImminent=%d, remainingRunTime=%fs", this, isSuspensionImminent, remainingRunTime);

m_isSuspended = true;
lowMemoryHandler(Critical::Yes);
@@ -2189,26 +2191,17 @@ void NetworkProcess::prepareToSuspend(bool isSuspensionImminent, CompletionHandl

void NetworkProcess::applicationDidEnterBackground()
{
if (!m_enterBackgroundTimestamp)
m_enterBackgroundTimestamp = MonotonicTime::now();

m_downloadManager.applicationDidEnterBackground();
}

void NetworkProcess::applicationWillEnterForeground()
{
if (m_enterBackgroundTimestamp)
m_enterBackgroundTimestamp = std::nullopt;

m_downloadManager.applicationWillEnterForeground();
}

void NetworkProcess::processDidResume(bool forForegroundActivity)
{
if (!m_enterBackgroundTimestamp)
RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume() forForegroundActivity=%d", this, forForegroundActivity);
else
RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume() forForegroundActivity=%d Process has been in background for %f seconds", this, forForegroundActivity, (MonotonicTime::now() - m_enterBackgroundTimestamp.value()).value());
RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume() forForegroundActivity=%d", this, forForegroundActivity);

m_isSuspended = false;

@@ -176,7 +176,7 @@ class NetworkProcess : public AuxiliaryProcess, private DownloadManager::Client,
void addStorageSession(PAL::SessionID, bool shouldUseTestingNetworkSession, const Vector<uint8_t>& uiProcessCookieStorageIdentifier, const SandboxExtension::Handle&);

void processWillSuspendImminentlyForTestingSync(CompletionHandler<void()>&&);
void prepareToSuspend(bool isSuspensionImminent, CompletionHandler<void()>&&);
void prepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime, CompletionHandler<void()>&&);
void processDidResume(bool forForegroundActivity);

CacheModel cacheModel() const { return m_cacheModel; }
@@ -531,7 +531,6 @@ class NetworkProcess : public AuxiliaryProcess, private DownloadManager::Client,
bool m_privateClickMeasurementEnabled { true };
bool m_ftpEnabled { false };
bool m_isSuspended { false };
std::optional<MonotonicTime> m_enterBackgroundTimestamp;
};

#if !PLATFORM(COCOA)
@@ -72,7 +72,7 @@ messages -> NetworkProcess LegacyReceiver {
SetCacheModelSynchronouslyForTesting(enum:uint8_t WebKit::CacheModel cacheModel) -> () Synchronous

ProcessWillSuspendImminentlyForTestingSync() -> () Synchronous
PrepareToSuspend(bool isSuspensionImminent) -> ()
PrepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime) -> ()
ProcessDidResume(bool forForegroundActivity)

PreconnectTo(PAL::SessionID sessionID, WebKit::WebPageProxyIdentifier webPageProxyID, WebCore::PageIdentifier webPageID, URL url, String userAgent, enum:uint8_t WebCore::StoredCredentialsPolicy storedCredentialsPolicy, enum:bool std::optional<WebKit::NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain, enum:bool WebKit::LastNavigationWasAppInitiated lastNavigationWasAppInitiated);
@@ -199,15 +199,15 @@ - (void)_processWillSuspendForTesting:(void (^)(void))completionHandler
completionHandler();
return;
}
_page->process().sendPrepareToSuspend(WebKit::IsSuspensionImminent::No, [completionHandler = makeBlockPtr(completionHandler)] {
_page->process().sendPrepareToSuspend(WebKit::IsSuspensionImminent::No, 0.0, [completionHandler = makeBlockPtr(completionHandler)] {
completionHandler();
});
}

- (void)_processWillSuspendImminentlyForTesting
{
if (_page)
_page->process().sendPrepareToSuspend(WebKit::IsSuspensionImminent::Yes, [] { });
_page->process().sendPrepareToSuspend(WebKit::IsSuspensionImminent::Yes, 0.0, [] { });
}

- (void)_processDidResumeForTesting
@@ -545,9 +545,9 @@ void GPUProcessProxy::removeSession(PAL::SessionID sessionID)
send(Messages::GPUProcess::RemoveSession { sessionID }, 0);
}

void GPUProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
void GPUProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, double remainingRunTime, CompletionHandler<void()>&& completionHandler)
{
sendWithAsyncReply(Messages::GPUProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes), WTFMove(completionHandler), 0, { }, ShouldStartProcessThrottlerActivity::No);
sendWithAsyncReply(Messages::GPUProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes, MonotonicTime::now() + Seconds(remainingRunTime)), WTFMove(completionHandler), 0, { }, ShouldStartProcessThrottlerActivity::No);
}

void GPUProcessProxy::sendProcessDidResume(ResumeReason)
@@ -126,7 +126,7 @@ class GPUProcessProxy final : public AuxiliaryProcessProxy, private ProcessThrot

// ProcessThrottlerClient
ASCIILiteral clientName() const final { return "GPUProcess"_s; }
void sendPrepareToSuspend(IsSuspensionImminent, CompletionHandler<void()>&&) final;
void sendPrepareToSuspend(IsSuspensionImminent, double remainingRunTime, CompletionHandler<void()>&&) final;
void sendProcessDidResume(ResumeReason) final;

// ProcessLauncher::Client
@@ -1374,11 +1374,13 @@ void NetworkProcessProxy::setSuspensionAllowedForTesting(bool allowed)
s_suspensionAllowedForTesting = allowed;
}

void NetworkProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
void NetworkProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, double remainingRunTime, CompletionHandler<void()>&& completionHandler)
{
if (!s_suspensionAllowedForTesting)
return completionHandler();
sendWithAsyncReply(Messages::NetworkProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes), WTFMove(completionHandler), 0, { }, ShouldStartProcessThrottlerActivity::No);

auto estimatedSuspendTime = MonotonicTime::now() + Seconds(remainingRunTime);
sendWithAsyncReply(Messages::NetworkProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes, estimatedSuspendTime), WTFMove(completionHandler), 0, { }, ShouldStartProcessThrottlerActivity::No);
}

void NetworkProcessProxy::sendProcessDidResume(ResumeReason reason)
@@ -270,7 +270,7 @@ class NetworkProcessProxy final : public AuxiliaryProcessProxy, private ProcessT
void getWindowSceneIdentifierForPaymentPresentation(WebPageProxyIdentifier, CompletionHandler<void(const String&)>&&);
#endif
// ProcessThrottlerClient
void sendPrepareToSuspend(IsSuspensionImminent, CompletionHandler<void()>&&) final;
void sendPrepareToSuspend(IsSuspensionImminent, double remainingRunTime, CompletionHandler<void()>&&) final;
void updateBundleIdentifier(const String&, CompletionHandler<void()>&&);
void clearBundleIdentifier(CompletionHandler<void()>&&);

@@ -42,6 +42,11 @@ ProcessAssertion::ProcessAssertion(ProcessID pid, const String& reason, ProcessA

ProcessAssertion::~ProcessAssertion() = default;

double ProcessAssertion::remainingRunTimeInSeconds(ProcessID)
{
return 0;
}

bool ProcessAssertion::isValid() const
{
return true;
@@ -70,6 +70,7 @@ class ProcessAssertion : public ThreadSafeRefCounted<ProcessAssertion>, public C
}
return assertion;
}
static double remainingRunTimeInSeconds(ProcessID);
virtual ~ProcessAssertion();

void setPrepareForInvalidationHandler(Function<void()>&& handler) { m_prepareForInvalidationHandler = WTFMove(handler); }
@@ -226,15 +226,15 @@ void ProcessThrottler::clearPendingRequestToSuspend()

void ProcessThrottler::sendPrepareToSuspendIPC(IsSuspensionImminent isSuspensionImminent)
{
PROCESSTHROTTLER_RELEASE_LOG("sendPrepareToSuspendIPC: isSuspensionImminent=%d", 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);
PROCESSTHROTTLER_RELEASE_LOG("sendPrepareToSuspendIPC: Not sending PrepareToSuspend() IPC because there is already one in flight (%" PRIu64 ")", *m_pendingRequestToSuspendID);
PROCESSTHROTTLER_RELEASE_LOG("sendPrepareToSuspendIPC: Not sending PrepareToSuspend(isSuspensionImminent=%d) IPC because there is already one in flight (%" PRIu64 ")", isSuspensionImminent == IsSuspensionImminent::Yes, *m_pendingRequestToSuspendID);
} else {
m_pendingRequestToSuspendID = generatePrepareToSuspendRequestID();
PROCESSTHROTTLER_RELEASE_LOG("sendPrepareToSuspendIPC: Sending PrepareToSuspend(%" PRIu64 ", isSuspensionImminent=%d) IPC", *m_pendingRequestToSuspendID, isSuspensionImminent == IsSuspensionImminent::Yes);
m_process.sendPrepareToSuspend(isSuspensionImminent, [this, weakThis = WeakPtr { *this }, requestToSuspendID = *m_pendingRequestToSuspendID]() mutable {
double remainingRunTime = ProcessAssertion::remainingRunTimeInSeconds(m_processIdentifier);
PROCESSTHROTTLER_RELEASE_LOG("sendPrepareToSuspendIPC: Sending PrepareToSuspend(%" PRIu64 ", isSuspensionImminent=%d) IPC, remainingRunTime=%fs", *m_pendingRequestToSuspendID, isSuspensionImminent == IsSuspensionImminent::Yes, remainingRunTime);
m_process.sendPrepareToSuspend(isSuspensionImminent, remainingRunTime, [this, weakThis = WeakPtr { *this }, requestToSuspendID = *m_pendingRequestToSuspendID]() mutable {
if (weakThis && m_pendingRequestToSuspendID && *m_pendingRequestToSuspendID == requestToSuspendID)
processReadyToSuspend();
});
@@ -36,7 +36,7 @@ class ProcessThrottlerClient {
public:
virtual ~ProcessThrottlerClient() { }

virtual void sendPrepareToSuspend(IsSuspensionImminent, CompletionHandler<void()>&&) = 0;
virtual void sendPrepareToSuspend(IsSuspensionImminent, double remainingRunTime, CompletionHandler<void()>&&) = 0;
enum ResumeReason : bool { ForegroundActivity, BackgroundActivity };
virtual void sendProcessDidResume(ResumeReason) = 0;
virtual void didSetAssertionType(ProcessAssertionType) { };
@@ -1443,10 +1443,10 @@ RefPtr<API::Object> WebProcessProxy::transformObjectsToHandles(API::Object* obje
return UserData::transform(object, Transformer());
}

void WebProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
void WebProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, double remainingRunTime, CompletionHandler<void()>&& completionHandler)
{
WEBPROCESSPROXY_RELEASE_LOG(ProcessSuspension, "sendPrepareToSuspend: isSuspensionImminent=%d", isSuspensionImminent == IsSuspensionImminent::Yes);
sendWithAsyncReply(Messages::WebProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes), WTFMove(completionHandler), 0, { }, ShouldStartProcessThrottlerActivity::No);
sendWithAsyncReply(Messages::WebProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes, MonotonicTime::now() + Seconds(remainingRunTime)), WTFMove(completionHandler), 0, { }, ShouldStartProcessThrottlerActivity::No);
}

void WebProcessProxy::sendProcessDidResume(ResumeReason)
@@ -327,7 +327,7 @@ class WebProcessProxy : public AuxiliaryProcessProxy, private ProcessThrottlerCl
void didStartProvisionalLoadForMainFrame(const URL&);

// ProcessThrottlerClient
void sendPrepareToSuspend(IsSuspensionImminent, CompletionHandler<void()>&&) final;
void sendPrepareToSuspend(IsSuspensionImminent, double remainingRunTime, CompletionHandler<void()>&&) final;
void sendProcessDidResume(ResumeReason) final;
void didSetAssertionType(ProcessAssertionType) final;
ASCIILiteral clientName() const final { return "WebProcess"_s; }
@@ -1590,7 +1590,7 @@ void WebsiteDataStore::terminateNetworkProcess()

void WebsiteDataStore::sendNetworkProcessPrepareToSuspendForTesting(CompletionHandler<void()>&& completionHandler)
{
networkProcess().sendPrepareToSuspend(IsSuspensionImminent::No, WTFMove(completionHandler));
networkProcess().sendPrepareToSuspend(IsSuspensionImminent::No, 0.0, WTFMove(completionHandler));
}

void WebsiteDataStore::sendNetworkProcessWillSuspendImminentlyForTesting()
@@ -367,6 +367,23 @@ - (void)assertion:(RBSAssertion *)assertion didInvalidateWithError:(NSError *)er
};
}

double ProcessAssertion::remainingRunTimeInSeconds(ProcessID pid)
{
RBSProcessIdentifier *processIdentifier = [RBSProcessIdentifier identifierWithPid:pid];
if (!processIdentifier) {
RELEASE_LOG_ERROR(ProcessSuspension, "ProcessAssertion::remainingRunTimeInSeconds failed to get identifier for process with PID=%d", pid);
return 0;
}

RBSProcessHandle *processHandle = [RBSProcessHandle handleForIdentifier:processIdentifier error:nil];
if (!processHandle) {
RELEASE_LOG_ERROR(ProcessSuspension, "ProcessAssertion::remainingRunTimeInSeconds failed to get handle for process with PID=%d", pid);
return 0;
}

return processHandle.activeLimitations.runTime;
}

void ProcessAssertion::acquireAsync(CompletionHandler<void()>&& completionHandler)
{
ASSERT(isMainRunLoop());
@@ -1473,9 +1473,11 @@ void WebProcess::pageActivityStateDidChange(PageIdentifier, OptionSet<WebCore::A
}
}

void WebProcess::prepareToSuspend(bool isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
void WebProcess::prepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime, CompletionHandler<void()>&& completionHandler)
{
WEBPROCESS_RELEASE_LOG(ProcessSuspension, "prepareToSuspend: isSuspensionImminent=%d", isSuspensionImminent);
auto nowTime = MonotonicTime::now();
double remainingRunTime = nowTime > estimatedSuspendTime ? (nowTime - estimatedSuspendTime).value() : 0.0;
WEBPROCESS_RELEASE_LOG(ProcessSuspension, "prepareToSuspend: isSuspensionImminent=%d, remainingRunTime=%fs", isSuspensionImminent, remainingRunTime);
SetForScope suspensionScope(m_isSuspending, true);
m_processIsSuspended = true;

@@ -291,7 +291,7 @@ class WebProcess : public AuxiliaryProcess

void setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds);

void prepareToSuspend(bool isSuspensionImminent, CompletionHandler<void()>&&);
void prepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime, CompletionHandler<void()>&&);
void processDidResume();

void sendPrewarmInformation(const URL&);
@@ -87,7 +87,7 @@ messages -> WebProcess LegacyReceiver NotRefCounted {
EnsureAutomationSessionProxy(String sessionIdentifier)
DestroyAutomationSessionProxy()

PrepareToSuspend(bool isSuspensionImminent) -> ()
PrepareToSuspend(bool isSuspensionImminent, MonotonicTime estimatedSuspendTime) -> ()
ProcessDidResume()

BackgroundResponsivenessPing()

0 comments on commit 2b4a6da

Please sign in to comment.