Title: [279495] trunk/Source
Revision
279495
Author
cdu...@apple.com
Date
2021-07-01 20:14:26 -0700 (Thu, 01 Jul 2021)

Log Message

[macOS] Suspend WebProcesses that are in the process cache
https://bugs.webkit.org/show_bug.cgi?id=227269

Reviewed by Geoffrey Garen.

Suspend WebProcesses that are in the process cache on macOS to make sure they use no CPU.

* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::setIsInProcessCache):
(WebKit::WebProcessProxy::platformSuspendProcess):
(WebKit::WebProcessProxy::platformResumeProcess):
* UIProcess/WebProcessProxy.h:
* UIProcess/mac/WebProcessProxyMac.mm:
(WebKit::WebProcessProxy::platformSuspendProcess):
(WebKit::WebProcessProxy::platformResumeProcess):
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::setIsInProcessCache):
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:

Modified Paths

Diff

Modified: trunk/Source/WebCore/workers/service/context/SWContextManager.cpp (279494 => 279495)


--- trunk/Source/WebCore/workers/service/context/SWContextManager.cpp	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebCore/workers/service/context/SWContextManager.cpp	2021-07-02 03:14:26 UTC (rev 279495)
@@ -143,6 +143,11 @@
         if (completionHandler)
             completionHandler();
 
+        if (m_pendingServiceWorkerTerminationRequests.isEmpty()) {
+            for (auto& handler : std::exchange(m_whenTerminationRequestsAreDoneHandlers, { }))
+                handler();
+        }
+
         // Spin the runloop before releasing the worker thread proxy, as there would otherwise be
         // a race towards its destruction.
         callOnMainThread([serviceWorker = WTFMove(serviceWorker)] { });
@@ -149,6 +154,14 @@
     });
 }
 
+void SWContextManager::whenTerminationRequestsAreDone(CompletionHandler<void()>&& completionHandler)
+{
+    if (m_pendingServiceWorkerTerminationRequests.isEmpty())
+        return completionHandler();
+
+    m_whenTerminationRequestsAreDoneHandlers.append(WTFMove(completionHandler));
+}
+
 void SWContextManager::forEachServiceWorkerThread(const WTF::Function<void(ServiceWorkerThreadProxy&)>& apply)
 {
     for (auto& workerThread : m_workerMap.values())

Modified: trunk/Source/WebCore/workers/service/context/SWContextManager.h (279494 => 279495)


--- trunk/Source/WebCore/workers/service/context/SWContextManager.h	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebCore/workers/service/context/SWContextManager.h	2021-07-02 03:14:26 UTC (rev 279495)
@@ -107,6 +107,8 @@
     static constexpr Seconds workerTerminationTimeout { 10_s };
     static constexpr Seconds syncWorkerTerminationTimeout { 100_ms }; // Only used by layout tests.
 
+    WEBCORE_EXPORT void whenTerminationRequestsAreDone(CompletionHandler<void()>&&);
+
 private:
     SWContextManager() = default;
 
@@ -128,6 +130,7 @@
         Timer m_timeoutTimer;
     };
     HashMap<ServiceWorkerIdentifier, std::unique_ptr<ServiceWorkerTerminationRequest>> m_pendingServiceWorkerTerminationRequests;
+    Vector<CompletionHandler<void()>> m_whenTerminationRequestsAreDoneHandlers;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (279494 => 279495)


--- trunk/Source/WebKit/ChangeLog	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebKit/ChangeLog	2021-07-02 03:14:26 UTC (rev 279495)
@@ -1,3 +1,25 @@
+2021-07-01  Chris Dumez  <cdu...@apple.com>
+
+        [macOS] Suspend WebProcesses that are in the process cache
+        https://bugs.webkit.org/show_bug.cgi?id=227269
+
+        Reviewed by Geoffrey Garen.
+
+        Suspend WebProcesses that are in the process cache on macOS to make sure they use no CPU.
+
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::setIsInProcessCache):
+        (WebKit::WebProcessProxy::platformSuspendProcess):
+        (WebKit::WebProcessProxy::platformResumeProcess):
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/mac/WebProcessProxyMac.mm:
+        (WebKit::WebProcessProxy::platformSuspendProcess):
+        (WebKit::WebProcessProxy::platformResumeProcess):
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::setIsInProcessCache):
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+
 2021-07-01  Alex Christensen  <achristen...@webkit.org>
 
         loadSimulatedRequest: should do same delegate callbacks as loadHTMLString and loadData

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (279494 => 279495)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2021-07-02 03:14:26 UTC (rev 279495)
@@ -289,8 +289,14 @@
     ASSERT(m_isInProcessCache != value);
     m_isInProcessCache = value;
 
-    send(Messages::WebProcess::SetIsInProcessCache(m_isInProcessCache), 0);
+    if (!m_isInProcessCache)
+        platformResumeProcess();
 
+    sendWithAsyncReply(Messages::WebProcess::SetIsInProcessCache(m_isInProcessCache), [weakThis = makeWeakPtr(*this), isEnteringProcessCache = value]() mutable {
+        if (isEnteringProcessCache && weakThis && weakThis->m_isInProcessCache)
+            weakThis->platformSuspendProcess();
+    });
+
     if (m_isInProcessCache) {
         // WebProcessProxy objects normally keep the process pool alive but we do not want this to be the case
         // for cached processes or it would leak the pool.
@@ -2003,6 +2009,16 @@
     PAL::systemBeep();
 }
 
+#if !PLATFORM(MAC)
+void WebProcessProxy::platformSuspendProcess()
+{
+}
+
+void WebProcessProxy::platformResumeProcess()
+{
+}
+#endif
+
 } // namespace WebKit
 
 #undef MESSAGE_CHECK

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (279494 => 279495)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-07-02 03:14:26 UTC (rev 279495)
@@ -471,6 +471,9 @@
 
     void processDidTerminateOrFailedToLaunch(ProcessTerminationReason);
 
+    void platformSuspendProcess();
+    void platformResumeProcess();
+
     // IPC::Connection::Client
     friend class WebConnectionToWebProcess;
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;

Modified: trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm (279494 => 279495)


--- trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm	2021-07-02 03:14:26 UTC (rev 279495)
@@ -31,6 +31,7 @@
 
 #import "WKFullKeyboardAccessWatcher.h"
 #import <Kernel/kern/cs_blobs.h>
+#import <signal.h>
 #import <wtf/ProcessPrivilege.h>
 #import <wtf/spi/cocoa/SecuritySPI.h>
 
@@ -78,6 +79,24 @@
     processPool().setDisplayLinkPreferredFramesPerSecond(*connection(), observerID, displayID, preferredFramesPerSecond);
 }
 
+void WebProcessProxy::platformSuspendProcess()
+{
+    RELEASE_LOG(Process, "%p - [PID=%i] WebProcessProxy::platformSuspendProcess", this, processIdentifier());
+    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    if (auto* connection = this->connection())
+        xpc_connection_kill(connection->xpcConnection(), SIGSTOP);
+    ALLOW_DEPRECATED_DECLARATIONS_END
+}
+
+void WebProcessProxy::platformResumeProcess()
+{
+    RELEASE_LOG(Process, "%p - [PID=%i] WebProcessProxy::platformResumeProcess", this, processIdentifier());
+    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    if (auto* connection = this->connection())
+        xpc_connection_kill(connection->xpcConnection(), SIGCONT);
+    ALLOW_DEPRECATED_DECLARATIONS_END
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)

Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (279494 => 279495)


--- trunk/Source/WebKit/WebProcess/WebProcess.cpp	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp	2021-07-02 03:14:26 UTC (rev 279495)
@@ -614,7 +614,7 @@
     m_hasSuspendedPageProxy = hasSuspendedPageProxy;
 }
 
-void WebProcess::setIsInProcessCache(bool isInProcessCache)
+void WebProcess::setIsInProcessCache(bool isInProcessCache, CompletionHandler<void()>&& completionHandler)
 {
 #if PLATFORM(COCOA)
     if (isInProcessCache) {
@@ -629,6 +629,18 @@
 #else
     UNUSED_PARAM(isInProcessCache);
 #endif
+
+#if ENABLE(SERVICE_WORKER)
+    if (isInProcessCache) {
+        // When calling the completion handler, the parent process may suspend us. We do not want to get suspended until pending requests to
+        // stop service workers are processed because this would be wasteful from a memory standpoint. Also, service worker termination
+        // requests have a timeout and this timeout would be reached if we suspended while it is being processed.
+        SWContextManager::singleton().whenTerminationRequestsAreDone(WTFMove(completionHandler));
+        return;
+    }
+#endif
+
+    completionHandler();
 }
 
 void WebProcess::markIsNoLongerPrewarmed()

Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (279494 => 279495)


--- trunk/Source/WebKit/WebProcess/WebProcess.h	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h	2021-07-02 03:14:26 UTC (rev 279495)
@@ -420,7 +420,7 @@
     void platformTerminate();
 
     void setHasSuspendedPageProxy(bool);
-    void setIsInProcessCache(bool);
+    void setIsInProcessCache(bool, CompletionHandler<void()>&&);
     void markIsNoLongerPrewarmed();
 
     void registerURLSchemeAsEmptyDocument(const String&);

Modified: trunk/Source/WebKit/WebProcess/WebProcess.messages.in (279494 => 279495)


--- trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2021-07-02 01:45:31 UTC (rev 279494)
+++ trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2021-07-02 03:14:26 UTC (rev 279495)
@@ -105,7 +105,7 @@
 #endif
 
     SetHasSuspendedPageProxy(bool hasSuspendedPageProxy);
-    SetIsInProcessCache(bool isInProcessCache)
+    SetIsInProcessCache(bool isInProcessCache) -> () Async
     MarkIsNoLongerPrewarmed()
     GetActivePagesOriginsForTesting() -> (Vector<String> activeOrigins) Async
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to