Diff
Modified: trunk/Source/WebKit/ChangeLog (276147 => 276148)
--- trunk/Source/WebKit/ChangeLog 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/ChangeLog 2021-04-16 18:41:22 UTC (rev 276148)
@@ -1,5 +1,101 @@
2021-04-16 Chris Dumez <[email protected]>
+ Exit the GPUProcess when under memory pressure if it is not being used
+ https://bugs.webkit.org/show_bug.cgi?id=224556
+
+ Reviewed by Darin Adler.
+
+ Exit the GPUProcess when under memory pressure if it is not being used. This will
+ help us save memory, especially until we are able to enable "DOM Rendering in
+ GPUProcess".
+
+ Note that when the GPUProcess is ready to exit, it sends an IPC to the UIProcess
+ in order to get terminated, instead of terminating itself. The reason I do this is
+ so that the UIProcess can distinguish a GPUProcess crash from a normal idle exit.
+
+ A/B testing shows:
+ - 5-8% PLUM3 progression on iPhone
+ - 2.5-4% PLUM3 progression on iPad
+ - No PLT5 regression on either iPhone or iPad.
+
+ * GPUProcess/GPUConnectionToWebProcess.cpp:
+ (WebKit::GPUConnectionToWebProcess::GPUConnectionToWebProcess):
+ (WebKit::GPUConnectionToWebProcess::allowsExitUnderMemoryPressure const):
+ (WebKit::GPUConnectionToWebProcess::releaseRenderingBackend):
+ (WebKit::GPUConnectionToWebProcess::releaseGraphicsContextGL):
+ * GPUProcess/GPUConnectionToWebProcess.h:
+ (WebKit::GPUConnectionToWebProcess::remoteMediaPlayerManagerProxy):
+ * GPUProcess/GPUProcess.cpp:
+ (WebKit::GPUProcess::removeGPUConnectionToWebProcess):
+ (WebKit::GPUProcess::canExitUnderMemoryPressure const):
+ (WebKit::GPUProcess::tryExitIfUnusedAndUnderMemoryPressure):
+ (WebKit::GPUProcess::tryExitIfUnused):
+ (WebKit::GPUProcess::lowMemoryHandler):
+ * GPUProcess/GPUProcess.h:
+ * GPUProcess/graphics/RemoteRenderingBackend.cpp:
+ (WebKit::RemoteRenderingBackend::allowsExitUnderMemoryPressure const):
+ * GPUProcess/graphics/RemoteRenderingBackend.h:
+ * GPUProcess/media/RemoteAudioDestinationManager.cpp:
+ (WebKit::RemoteAudioDestinationManager::deleteAudioDestination):
+ (WebKit::RemoteAudioDestinationManager::allowsExitUnderMemoryPressure const):
+ * GPUProcess/media/RemoteAudioDestinationManager.h:
+ * GPUProcess/media/RemoteCDMFactoryProxy.cpp:
+ (WebKit::RemoteCDMFactoryProxy::removeInstance):
+ (WebKit::RemoteCDMFactoryProxy::allowsExitUnderMemoryPressure const):
+ * GPUProcess/media/RemoteCDMFactoryProxy.h:
+ * GPUProcess/media/RemoteImageDecoderAVFProxy.cpp:
+ (WebKit::RemoteImageDecoderAVFProxy::deleteDecoder):
+ (WebKit::RemoteImageDecoderAVFProxy::allowsExitUnderMemoryPressure const):
+ * GPUProcess/media/RemoteImageDecoderAVFProxy.h:
+ * GPUProcess/media/RemoteLegacyCDMFactoryProxy.cpp:
+ (WebKit::RemoteLegacyCDMFactoryProxy::removeSession):
+ (WebKit::RemoteLegacyCDMFactoryProxy::allowsExitUnderMemoryPressure const):
+ * GPUProcess/media/RemoteLegacyCDMFactoryProxy.h:
+ * GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp:
+ (WebKit::RemoteMediaPlayerManagerProxy::deleteMediaPlayer):
+ (WebKit::RemoteMediaPlayerManagerProxy::allowsExitUnderMemoryPressure const):
+ * GPUProcess/media/RemoteMediaPlayerManagerProxy.h:
+ * GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.cpp:
+ (WebKit::RemoteAudioMediaStreamTrackRendererManager::allowsExitUnderMemoryPressure const):
+ * GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.h:
+ * GPUProcess/webrtc/RemoteMediaRecorderManager.cpp:
+ (WebKit::RemoteMediaRecorderManager::releaseRecorder):
+ (WebKit::RemoteMediaRecorderManager::allowsExitUnderMemoryPressure const):
+ * GPUProcess/webrtc/RemoteMediaRecorderManager.h:
+ * GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.cpp:
+ (WebKit::RemoteSampleBufferDisplayLayerManager::allowsExitUnderMemoryPressure const):
+ * GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.h:
+ * Shared/ProcessTerminationReason.h:
+ * UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
+ (WebKit::UserMediaCaptureManagerProxy::hasSourceProxies const):
+ * UIProcess/Cocoa/UserMediaCaptureManagerProxy.h:
+ * UIProcess/GPU/GPUProcessProxy.cpp:
+ (WebKit::GPUProcessProxy::gpuProcessExited):
+ (WebKit::GPUProcessProxy::processIsReadyToExit):
+ (WebKit::GPUProcessProxy::didClose):
+ (WebKit::GPUProcessProxy::didFinishLaunching):
+ * UIProcess/GPU/GPUProcessProxy.h:
+ * UIProcess/GPU/GPUProcessProxy.messages.in:
+ * UIProcess/PageClient.h:
+ (WebKit::PageClient::gpuProcessDidExit):
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::gpuProcessExited):
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::gpuProcessExited):
+ * UIProcess/WebProcessPool.h:
+ * UIProcess/WebProcessProxy.cpp:
+ (WebKit::WebProcessProxy::gpuProcessExited):
+ * UIProcess/WebProcessProxy.h:
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::gpuProcessDidExit):
+ * UIProcess/ios/WKContentView.h:
+ * UIProcess/ios/WKContentView.mm:
+ (-[WKContentView _gpuProcessDidExit]):
+
+2021-04-16 Chris Dumez <[email protected]>
+
Early IPC messages to a WorkQueueMessageReceiver may get processed out of order
https://bugs.webkit.org/show_bug.cgi?id=224623
Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -189,7 +189,7 @@
#if HAVE(TASK_IDENTITY_TOKEN)
, m_webProcessIdentityToken(WTFMove(parameters.webProcessIdentityToken))
#endif
- , m_remoteMediaPlayerManagerProxy(makeUnique<RemoteMediaPlayerManagerProxy>(*this))
+ , m_remoteMediaPlayerManagerProxy(makeUniqueRef<RemoteMediaPlayerManagerProxy>(*this))
, m_sessionID(sessionID)
#if PLATFORM(COCOA) && USE(LIBWEBRTC)
, m_libWebRTCCodecsProxy(LibWebRTCCodecsProxy::create(*this))
@@ -267,6 +267,49 @@
}
#endif
+bool GPUConnectionToWebProcess::allowsExitUnderMemoryPressure() const
+{
+ for (auto& remoteRenderingBackend : m_remoteRenderingBackendMap.values()) {
+ if (!remoteRenderingBackend->allowsExitUnderMemoryPressure())
+ return false;
+ }
+#if ENABLE(WEBGL)
+ if (!m_remoteGraphicsContextGLMap.isEmpty())
+ return false;
+#endif
+ if (!m_remoteMediaPlayerManagerProxy->allowsExitUnderMemoryPressure())
+ return false;
+#if ENABLE(WEB_AUDIO)
+ if (m_remoteAudioDestinationManager && !m_remoteAudioDestinationManager->allowsExitUnderMemoryPressure())
+ return false;
+#endif
+#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
+ if (m_userMediaCaptureManagerProxy && m_userMediaCaptureManagerProxy->hasSourceProxies())
+ return false;
+ if (!m_audioTrackRendererManager->allowsExitUnderMemoryPressure())
+ return false;
+ if (!m_sampleBufferDisplayLayerManager->allowsExitUnderMemoryPressure())
+ return false;
+#endif
+#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
+ if (m_remoteMediaRecorderManager && !m_remoteMediaRecorderManager->allowsExitUnderMemoryPressure())
+ return false;
+#endif
+#if HAVE(AVASSETREADER)
+ if (m_imageDecoderAVFProxy && !m_imageDecoderAVFProxy->allowsExitUnderMemoryPressure())
+ return false;
+#endif
+#if ENABLE(ENCRYPTED_MEDIA)
+ if (m_cdmFactoryProxy && !m_cdmFactoryProxy->allowsExitUnderMemoryPressure())
+ return false;
+#endif
+#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
+ if (m_legacyCdmFactoryProxy && !m_legacyCdmFactoryProxy->allowsExitUnderMemoryPressure())
+ return false;
+#endif
+ return true;
+}
+
Logger& GPUConnectionToWebProcess::logger()
{
if (!m_logger) {
@@ -319,8 +362,9 @@
return *m_userMediaCaptureManagerProxy;
}
+#endif
-#if HAVE(AVASSETWRITERDELEGATE)
+#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
RemoteMediaRecorderManager& GPUConnectionToWebProcess::mediaRecorderManager()
{
if (!m_remoteMediaRecorderManager)
@@ -329,7 +373,6 @@
return *m_remoteMediaRecorderManager;
}
#endif
-#endif // PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
#if ENABLE(ENCRYPTED_MEDIA)
RemoteCDMFactoryProxy& GPUConnectionToWebProcess::cdmFactoryProxy()
@@ -374,6 +417,7 @@
{
bool found = m_remoteRenderingBackendMap.remove(renderingBackendIdentifier);
ASSERT_UNUSED(found, found);
+ gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
#if ENABLE(WEBGL)
@@ -393,6 +437,8 @@
void GPUConnectionToWebProcess::releaseGraphicsContextGL(GraphicsContextGLIdentifier graphicsContextGLIdentifier)
{
m_remoteGraphicsContextGLMap.remove(graphicsContextGLIdentifier);
+ if (m_remoteGraphicsContextGLMap.isEmpty())
+ gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
void GPUConnectionToWebProcess::releaseGraphicsContextGLForTesting(GraphicsContextGLIdentifier identifier)
@@ -537,7 +583,8 @@
userMediaCaptureManagerProxy().didReceiveMessageFromGPUProcess(connection, decoder);
return true;
}
-#if HAVE(AVASSETWRITERDELEGATE)
+#endif
+#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
if (decoder.messageReceiverName() == Messages::RemoteMediaRecorderManager::messageReceiverName()) {
mediaRecorderManager().didReceiveMessageFromWebProcess(connection, decoder);
return true;
@@ -546,8 +593,7 @@
mediaRecorderManager().didReceiveRemoteMediaRecorderMessage(connection, decoder);
return true;
}
-#endif // HAVE(AVASSETWRITERDELEGATE)
-#endif // PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
+#endif
#if ENABLE(ENCRYPTED_MEDIA)
if (decoder.messageReceiverName() == Messages::RemoteCDMFactoryProxy::messageReceiverName()) {
cdmFactoryProxy().didReceiveMessageFromWebProcess(connection, decoder);
Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -132,7 +132,7 @@
#endif
RemoteMediaEngineConfigurationFactoryProxy& mediaEngineConfigurationFactoryProxy();
- RemoteMediaPlayerManagerProxy& remoteMediaPlayerManagerProxy() { return *m_remoteMediaPlayerManagerProxy; }
+ RemoteMediaPlayerManagerProxy& remoteMediaPlayerManagerProxy() { return m_remoteMediaPlayerManagerProxy.get(); }
#if USE(AUDIO_SESSION)
RemoteAudioSessionProxyManager& audioSessionManager();
@@ -144,6 +144,8 @@
void updateSupportedRemoteCommands();
+ bool allowsExitUnderMemoryPressure() const;
+
void terminateWebProcess();
#if ENABLE(WEBGL)
void releaseGraphicsContextGLForTesting(GraphicsContextGLIdentifier);
@@ -156,10 +158,10 @@
#endif
#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
UserMediaCaptureManagerProxy& userMediaCaptureManagerProxy();
-#if HAVE(AVASSETWRITERDELEGATE)
+#endif
+#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
RemoteMediaRecorderManager& mediaRecorderManager();
#endif
-#endif
void createRenderingBackend(RemoteRenderingBackendCreationParameters&&);
void releaseRenderingBackend(RenderingBackendIdentifier);
@@ -228,7 +230,7 @@
std::unique_ptr<RemoteAudioDestinationManager> m_remoteAudioDestinationManager;
#endif
std::unique_ptr<RemoteMediaResourceManager> m_remoteMediaResourceManager;
- std::unique_ptr<RemoteMediaPlayerManagerProxy> m_remoteMediaPlayerManagerProxy;
+ UniqueRef<RemoteMediaPlayerManagerProxy> m_remoteMediaPlayerManagerProxy;
PAL::SessionID m_sessionID;
#if PLATFORM(COCOA) && USE(LIBWEBRTC)
Ref<LibWebRTCCodecsProxy> m_libWebRTCCodecsProxy;
@@ -237,10 +239,10 @@
std::unique_ptr<UserMediaCaptureManagerProxy> m_userMediaCaptureManagerProxy;
Ref<RemoteAudioMediaStreamTrackRendererManager> m_audioTrackRendererManager;
Ref<RemoteSampleBufferDisplayLayerManager> m_sampleBufferDisplayLayerManager;
-#if HAVE(AVASSETWRITERDELEGATE)
+#endif
+#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
std::unique_ptr<RemoteMediaRecorderManager> m_remoteMediaRecorderManager;
#endif
-#endif
#if ENABLE(MEDIA_STREAM)
bool m_allowsAudioCapture { false };
bool m_allowsVideoCapture { false };
Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/GPUProcess.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -111,6 +111,7 @@
{
ASSERT(m_webProcessConnections.contains(connection.webProcessIdentifier()));
m_webProcessConnections.remove(connection.webProcessIdentifier());
+ tryExitIfUnusedAndUnderMemoryPressure();
}
void GPUProcess::connectionToWebProcessClosed(IPC::Connection& connection)
@@ -122,8 +123,40 @@
return m_webProcessConnections.isEmpty();
}
+bool GPUProcess::canExitUnderMemoryPressure() const
+{
+ ASSERT(isMainRunLoop());
+ for (auto& webProcessConnection : m_webProcessConnections.values()) {
+ if (!webProcessConnection->allowsExitUnderMemoryPressure())
+ return false;
+ }
+ return true;
+}
+
+void GPUProcess::tryExitIfUnusedAndUnderMemoryPressure()
+{
+ ASSERT(isMainRunLoop());
+ if (!MemoryPressureHandler::singleton().isUnderMemoryPressure())
+ return;
+
+ tryExitIfUnused();
+}
+
+void GPUProcess::tryExitIfUnused()
+{
+ ASSERT(isMainRunLoop());
+ if (!canExitUnderMemoryPressure())
+ return;
+
+ RELEASE_LOG(Process, "GPUProcess::tryExitIfUnused: GPUProcess is exiting because we are under memory pressure and the process is no longer useful.");
+ parentProcessConnection()->send(Messages::GPUProcessProxy::ProcessIsReadyToExit(), 0);
+}
+
void GPUProcess::lowMemoryHandler(Critical critical, Synchronous synchronous)
{
+ RELEASE_LOG(Process, "GPUProcess::lowMemoryHandler: critical=%d, synchronous=%d", critical == Critical::Yes, synchronous == Synchronous::Yes);
+ tryExitIfUnused();
+
WebCore::releaseGraphicsMemory(critical, synchronous);
}
Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/GPUProcess.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -92,6 +92,8 @@
void enableVP9Decoders(bool shouldEnableVP8Decoder, bool shouldEnableVP9Decoder, bool shouldEnableVP9SWDecoder);
#endif
+ void tryExitIfUnusedAndUnderMemoryPressure();
+
private:
void lowMemoryHandler(Critical, Synchronous);
@@ -101,6 +103,9 @@
void initializeSandbox(const AuxiliaryProcessInitializationParameters&, SandboxInitializationParameters&) override;
bool shouldTerminate() override;
+ void tryExitIfUnused();
+ bool canExitUnderMemoryPressure() const;
+
// IPC::Connection::Client
void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -597,6 +597,11 @@
m_renderingResourcesRequest = { };
}
+bool RemoteRenderingBackend::allowsExitUnderMemoryPressure() const
+{
+ return m_remoteResourceCache.imageBuffers().isEmpty() && m_remoteResourceCache.nativeImages().isEmpty();
+}
+
} // namespace WebKit
#endif // ENABLE(GPU_PROCESS)
Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -83,6 +83,8 @@
void populateGetImageDataSharedMemory(WebCore::ImageData*);
+ bool allowsExitUnderMemoryPressure() const;
+
// Runs Function in RemoteRenderingBackend task queue.
void dispatch(Function<void()>&&);
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -29,6 +29,7 @@
#if ENABLE(GPU_PROCESS) && ENABLE(WEB_AUDIO)
#include "GPUConnectionToWebProcess.h"
+#include "GPUProcess.h"
#include <WebCore/AudioUtilities.h>
#include <wtf/ThreadSafeRefCounted.h>
@@ -173,6 +174,9 @@
if (destination)
destination->scheduleGracefulShutdownIfNeeded();
completionHandler();
+
+ if (allowsExitUnderMemoryPressure())
+ m_gpuConnectionToWebProcess.gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
void RemoteAudioDestinationManager::startAudioDestination(RemoteAudioDestinationIdentifier identifier, CompletionHandler<void(bool)>&& completionHandler)
@@ -203,6 +207,11 @@
}
#endif
+bool RemoteAudioDestinationManager::allowsExitUnderMemoryPressure() const
+{
+ return m_audioDestinations.isEmpty();
+}
+
} // namespace WebKit
#endif // ENABLE(GPU_PROCESS) && ENABLE(WEB_AUDIO)
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -56,6 +56,8 @@
bool didReceiveSyncMessageFromWebProcess(IPC::Connection& connection, IPC::Decoder& decoder, UniqueRef<IPC::Encoder>& encoder) { return didReceiveSyncMessage(connection, decoder, encoder); }
void didReceiveMessageFromWebProcess(IPC::Connection& connection, IPC::Decoder& decoder) { didReceiveMessage(connection, decoder); }
+ bool allowsExitUnderMemoryPressure() const;
+
private:
void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
bool didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, UniqueRef<IPC::Encoder>&);
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteCDMFactoryProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteCDMFactoryProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteCDMFactoryProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -28,6 +28,7 @@
#if ENABLE(GPU_PROCESS) && ENABLE(ENCRYPTED_MEDIA)
+#include "GPUProcess.h"
#include "RemoteCDMConfiguration.h"
#include "RemoteCDMInstanceProxy.h"
#include "RemoteCDMInstanceSessionProxy.h"
@@ -142,6 +143,8 @@
{
ASSERT(m_instances.contains(identifier));
m_instances.remove(identifier);
+ if (m_gpuConnectionToWebProcess && allowsExitUnderMemoryPressure())
+ m_gpuConnectionToWebProcess->gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
RemoteCDMInstanceProxy* RemoteCDMFactoryProxy::getInstance(const RemoteCDMInstanceIdentifier& identifier)
@@ -161,6 +164,11 @@
m_sessions.remove(identifier);
}
+bool RemoteCDMFactoryProxy::allowsExitUnderMemoryPressure() const
+{
+ return m_instances.isEmpty();
}
+}
+
#endif
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteCDMFactoryProxy.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteCDMFactoryProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteCDMFactoryProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -70,6 +70,8 @@
GPUConnectionToWebProcess* gpuConnectionToWebProcess() { return m_gpuConnectionToWebProcess.get(); }
+ bool allowsExitUnderMemoryPressure() const;
+
private:
friend class GPUProcessConnection;
// IPC::MessageReceiver
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteImageDecoderAVFProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteImageDecoderAVFProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteImageDecoderAVFProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -29,6 +29,7 @@
#if ENABLE(GPU_PROCESS) && HAVE(AVASSETREADER)
#include "GPUConnectionToWebProcess.h"
+#include "GPUProcess.h"
#include "RemoteImageDecoderAVFManagerMessages.h"
#include "RemoteImageDecoderAVFProxyMessages.h"
#include "WebCoreArgumentCoders.h"
@@ -70,6 +71,8 @@
return;
m_imageDecoders.take(identifier);
+ if (m_connectionToWebProcess && allowsExitUnderMemoryPressure())
+ m_connectionToWebProcess->gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
void RemoteImageDecoderAVFProxy::encodedDataStatusChanged(ImageDecoderIdentifier identifier)
@@ -141,6 +144,11 @@
imageDecoder->clearFrameBufferCache(std::min(index, imageDecoder->frameCount() - 1));
}
+bool RemoteImageDecoderAVFProxy::allowsExitUnderMemoryPressure() const
+{
+ return m_imageDecoders.isEmpty();
}
+}
+
#endif
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteImageDecoderAVFProxy.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteImageDecoderAVFProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteImageDecoderAVFProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -50,6 +50,8 @@
void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
bool didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, UniqueRef<IPC::Encoder>&) final;
+ bool allowsExitUnderMemoryPressure() const;
+
private:
void createDecoder(const IPC::DataReference&, const String& mimeType, CompletionHandler<void(Optional<WebCore::ImageDecoderIdentifier>&&)>&&);
void deleteDecoder(WebCore::ImageDecoderIdentifier);
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMFactoryProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMFactoryProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMFactoryProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -29,6 +29,7 @@
#if ENABLE(GPU_PROCESS) && ENABLE(LEGACY_ENCRYPTED_MEDIA)
#include "GPUConnectionToWebProcess.h"
+#include "GPUProcess.h"
#include "RemoteLegacyCDMProxy.h"
#include "RemoteLegacyCDMProxyMessages.h"
#include "RemoteLegacyCDMSessionProxy.h"
@@ -151,6 +152,9 @@
ASSERT(m_sessions.contains(identifier));
m_sessions.remove(identifier);
+
+ if (m_gpuConnectionToWebProcess && allowsExitUnderMemoryPressure())
+ m_gpuConnectionToWebProcess->gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
RemoteLegacyCDMSessionProxy* RemoteLegacyCDMFactoryProxy::getSession(const RemoteLegacyCDMSessionIdentifier& identifier) const
@@ -161,6 +165,11 @@
return nullptr;
}
+bool RemoteLegacyCDMFactoryProxy::allowsExitUnderMemoryPressure() const
+{
+ return m_sessions.isEmpty();
}
+}
+
#endif
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMFactoryProxy.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMFactoryProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMFactoryProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -64,6 +64,8 @@
GPUConnectionToWebProcess* gpuConnectionToWebProcess() { return m_gpuConnectionToWebProcess.get(); }
+ bool allowsExitUnderMemoryPressure() const;
+
private:
friend class GPUProcessConnection;
// IPC::MessageReceiver
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -29,6 +29,7 @@
#if ENABLE(GPU_PROCESS)
#include "GPUConnectionToWebProcess.h"
+#include "GPUProcess.h"
#include "Logging.h"
#include "RemoteMediaPlayerConfiguration.h"
#include "RemoteMediaPlayerManagerProxyMessages.h"
@@ -72,9 +73,13 @@
void RemoteMediaPlayerManagerProxy::deleteMediaPlayer(MediaPlayerIdentifier identifier)
{
ASSERT(RunLoop::isMain());
- auto locker = holdLock(m_proxiesLock);
- if (auto proxy = m_proxies.take(identifier))
- proxy->invalidate();
+ {
+ auto locker = holdLock(m_proxiesLock);
+ if (auto proxy = m_proxies.take(identifier))
+ proxy->invalidate();
+ }
+ if (m_gpuConnectionToWebProcess && allowsExitUnderMemoryPressure())
+ m_gpuConnectionToWebProcess->gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
void RemoteMediaPlayerManagerProxy::getSupportedTypes(MediaPlayerEnums::MediaEngineIdentifier engineIdentifier, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
@@ -179,6 +184,11 @@
return nullptr;
}
+bool RemoteMediaPlayerManagerProxy::allowsExitUnderMemoryPressure() const
+{
+ return m_proxies.isEmpty();
+}
+
#if !RELEASE_LOG_DISABLED
Logger& RemoteMediaPlayerManagerProxy::logger()
{
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -65,6 +65,7 @@
bool didReceiveSyncPlayerMessage(IPC::Connection&, IPC::Decoder&, UniqueRef<IPC::Encoder>&);
RefPtr<WebCore::MediaPlayer> mediaPlayer(const WebCore::MediaPlayerIdentifier&);
+ bool allowsExitUnderMemoryPressure() const;
private:
// IPC::MessageReceiver
Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -88,6 +88,11 @@
m_renderers.remove(identifier);
}
+bool RemoteAudioMediaStreamTrackRendererManager::allowsExitUnderMemoryPressure() const
+{
+ return m_renderers.isEmpty();
}
+}
+
#endif // PLATFORM(COCOA) && ENABLE(GPU_PROCESS) && ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -60,6 +60,8 @@
void close();
+ bool allowsExitUnderMemoryPressure() const;
+
private:
explicit RemoteAudioMediaStreamTrackRendererManager(GPUConnectionToWebProcess&);
void startListeningForIPC();
Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -65,8 +65,15 @@
void RemoteMediaRecorderManager::releaseRecorder(MediaRecorderIdentifier identifier)
{
m_recorders.remove(identifier);
+ if (allowsExitUnderMemoryPressure())
+ m_gpuConnectionToWebProcess.gpuProcess().tryExitIfUnusedAndUnderMemoryPressure();
}
+bool RemoteMediaRecorderManager::allowsExitUnderMemoryPressure() const
+{
+ return m_recorders.isEmpty();
}
+}
+
#endif
Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -58,6 +58,8 @@
void didReceiveRemoteMediaRecorderMessage(IPC::Connection&, IPC::Decoder&);
void didReceiveMessageFromWebProcess(IPC::Connection& connection, IPC::Decoder& decoder) { didReceiveMessage(connection, decoder); }
+ bool allowsExitUnderMemoryPressure() const;
+
private:
// IPC::MessageReceiver
void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.cpp (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -103,6 +103,11 @@
});
}
+bool RemoteSampleBufferDisplayLayerManager::allowsExitUnderMemoryPressure() const
+{
+ return m_layers.isEmpty();
}
+}
+
#endif // PLATFORM(COCOA) && ENABLE(GPU_PROCESS) && ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.h (276147 => 276148)
--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -59,6 +59,8 @@
void close();
+ bool allowsExitUnderMemoryPressure() const;
+
private:
explicit RemoteSampleBufferDisplayLayerManager(GPUConnectionToWebProcess&);
void startListeningForIPC();
Modified: trunk/Source/WebKit/Shared/ProcessTerminationReason.h (276147 => 276148)
--- trunk/Source/WebKit/Shared/ProcessTerminationReason.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/Shared/ProcessTerminationReason.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -37,4 +37,9 @@
RequestedByGPUProcess
};
+enum class GPUProcessTerminationReason {
+ Crash,
+ IdleExit
+};
+
}
Modified: trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -368,8 +368,13 @@
m_orientationNotifier.orientationChanged(orientation);
}
+bool UserMediaCaptureManagerProxy::hasSourceProxies() const
+{
+ return !m_proxies.isEmpty();
}
+}
+
#undef MESSAGE_CHECK
#endif
Modified: trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -67,6 +67,8 @@
void didReceiveMessageFromGPUProcess(IPC::Connection& connection, IPC::Decoder& decoder) { didReceiveMessage(connection, decoder); }
+ bool hasSourceProxies() const;
+
private:
// IPC::MessageReceiver
void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
Modified: trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -285,19 +285,37 @@
}, 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
}
-void GPUProcessProxy::gpuProcessCrashed()
+void GPUProcessProxy::gpuProcessExited(GPUProcessTerminationReason reason)
{
+ auto protectedThis = makeRef(*this);
+
+ switch (reason) {
+ case GPUProcessTerminationReason::Crash:
+ RELEASE_LOG_ERROR(Process, "%p - GPUProcessProxy::gpuProcessExited: reason=crash", this);
+ break;
+ case GPUProcessTerminationReason::IdleExit:
+ RELEASE_LOG(Process, "%p - GPUProcessProxy::gpuProcessExited: reason=idle-exit", this);
+ break;
+ }
+
if (singleton() == this)
singleton() = nullptr;
for (auto& processPool : WebProcessPool::allProcessPools())
- processPool->gpuProcessCrashed(processIdentifier());
+ processPool->gpuProcessExited(processIdentifier(), reason);
}
+void GPUProcessProxy::processIsReadyToExit()
+{
+ RELEASE_LOG(Process, "%p - GPUProcessProxy::processIsReadyToExit:", this);
+ terminate();
+ gpuProcessExited(GPUProcessTerminationReason::IdleExit); // May cause |this| to get deleted.
+}
+
void GPUProcessProxy::didClose(IPC::Connection&)
{
- // This will cause us to be deleted.
- gpuProcessCrashed();
+ RELEASE_LOG_ERROR(Process, "%p - GPUProcessProxy::didClose:", this);
+ gpuProcessExited(GPUProcessTerminationReason::Crash); // May cause |this| to get deleted.
}
void GPUProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::MessageName messageName)
@@ -319,7 +337,7 @@
AuxiliaryProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
if (!IPC::Connection::identifierIsValid(connectionIdentifier)) {
- gpuProcessCrashed();
+ gpuProcessExited(GPUProcessTerminationReason::Crash);
return;
}
Modified: trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -30,6 +30,7 @@
#include "AuxiliaryProcessProxy.h"
#include "GPUProcessProxyMessagesReplies.h"
#include "ProcessLauncher.h"
+#include "ProcessTerminationReason.h"
#include "ProcessThrottler.h"
#include "ProcessThrottlerClient.h"
#include "WebPageProxyIdentifier.h"
@@ -101,7 +102,7 @@
void connectionWillOpen(IPC::Connection&) override;
void processWillShutDown(IPC::Connection&) override;
- void gpuProcessCrashed();
+ void gpuProcessExited(GPUProcessTerminationReason);
// ProcessThrottlerClient
ASCIILiteral clientName() const final { return "GPUProcess"_s; }
@@ -117,6 +118,7 @@
void didReceiveInvalidMessage(IPC::Connection&, IPC::MessageName) override;
void terminateWebProcess(WebCore::ProcessIdentifier);
+ void processIsReadyToExit();
#if HAVE(VISIBILITY_PROPAGATION_VIEW)
void didCreateContextForVisibilityPropagation(WebPageProxyIdentifier, WebCore::PageIdentifier, LayerHostingContextID);
Modified: trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.messages.in (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.messages.in 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.messages.in 2021-04-16 18:41:22 UTC (rev 276148)
@@ -28,6 +28,7 @@
DidCreateContextForVisibilityPropagation(WebKit::WebPageProxyIdentifier pageProxyID, WebCore::PageIdentifier pageID, WebKit::LayerHostingContextID contextID)
#endif
+ ProcessIsReadyToExit()
TerminateWebProcess(WebCore::ProcessIdentifier webProcessIdentifier)
}
Modified: trunk/Source/WebKit/UIProcess/PageClient.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/PageClient.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/PageClient.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -342,7 +342,7 @@
#endif
#if ENABLE(GPU_PROCESS)
- virtual void gpuProcessCrashed() { }
+ virtual void gpuProcessDidExit() { }
#endif
virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&, bool wasEventHandled) = 0;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -10397,13 +10397,13 @@
#endif
#if ENABLE(GPU_PROCESS)
-void WebPageProxy::gpuProcessCrashed()
+void WebPageProxy::gpuProcessExited(GPUProcessTerminationReason)
{
#if HAVE(VISIBILITY_PROPAGATION_VIEW)
m_contextIDForVisibilityPropagationInGPUProcess = 0;
#endif
- pageClient().gpuProcessCrashed();
+ pageClient().gpuProcessDidExit();
#if ENABLE(MEDIA_STREAM)
bool shouldAllowAudioCapture = isCapturingAudio() && preferences().captureAudioInGPUProcessEnabled();
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -1237,7 +1237,7 @@
#endif
#if ENABLE(GPU_PROCESS)
- void gpuProcessCrashed();
+ void gpuProcessExited(GPUProcessTerminationReason);
#endif
virtual void enterAcceleratedCompositingMode(const LayerTreeContext&);
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -504,23 +504,27 @@
return *m_gpuProcess;
}
-void WebProcessPool::gpuProcessCrashed(ProcessID identifier)
+void WebProcessPool::gpuProcessExited(ProcessID identifier, GPUProcessTerminationReason reason)
{
- WEBPROCESSPOOL_RELEASE_LOG_ERROR(Process, "gpuProcessCrashed: PID=%d", identifier);
+ WEBPROCESSPOOL_RELEASE_LOG(Process, "gpuProcessDidExit: PID=%d, reason=%u", identifier, static_cast<unsigned>(reason));
m_gpuProcess = nullptr;
- m_client.gpuProcessDidCrash(this, identifier);
+ if (reason == GPUProcessTerminationReason::Crash)
+ m_client.gpuProcessDidCrash(this, identifier);
+
Vector<Ref<WebProcessProxy>> processes = m_processes;
for (auto& process : processes)
- process->gpuProcessCrashed();
+ process->gpuProcessExited(reason);
- if (++m_recentGPUProcessCrashCount > maximumGPUProcessRelaunchAttemptsBeforeKillingWebProcesses) {
- WEBPROCESSPOOL_RELEASE_LOG_ERROR(Process, "gpuProcessCrashed: GPU Process has crashed more than %u times in the last %g seconds, terminating all WebProcesses", maximumGPUProcessRelaunchAttemptsBeforeKillingWebProcesses, resetGPUProcessCrashCountDelay.seconds());
- m_resetGPUProcessCrashCountTimer.stop();
- m_recentGPUProcessCrashCount = 0;
- terminateAllWebContentProcesses();
- } else if (!m_resetGPUProcessCrashCountTimer.isActive())
- m_resetGPUProcessCrashCountTimer.startOneShot(resetGPUProcessCrashCountDelay);
+ if (reason == GPUProcessTerminationReason::Crash) {
+ if (++m_recentGPUProcessCrashCount > maximumGPUProcessRelaunchAttemptsBeforeKillingWebProcesses) {
+ WEBPROCESSPOOL_RELEASE_LOG_ERROR(Process, "gpuProcessDidExit: GPU Process has crashed more than %u times in the last %g seconds, terminating all WebProcesses", maximumGPUProcessRelaunchAttemptsBeforeKillingWebProcesses, resetGPUProcessCrashCountDelay.seconds());
+ m_resetGPUProcessCrashCountTimer.stop();
+ m_recentGPUProcessCrashCount = 0;
+ terminateAllWebContentProcesses();
+ } else if (!m_resetGPUProcessCrashCountTimer.isActive())
+ m_resetGPUProcessCrashCountTimer.startOneShot(resetGPUProcessCrashCountDelay);
+ }
}
void WebProcessPool::getGPUProcessConnection(WebProcessProxy& webProcessProxy, GPUProcessConnectionParameters&& parameters, Messages::WebProcessProxy::GetGPUProcessConnection::DelayedReply&& reply)
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -357,7 +357,7 @@
void textCheckerStateChanged();
#if ENABLE(GPU_PROCESS)
- void gpuProcessCrashed(ProcessID);
+ void gpuProcessExited(ProcessID, GPUProcessTerminationReason);
void getGPUProcessConnection(WebProcessProxy&, GPUProcessConnectionParameters&&, Messages::WebProcessProxy::GetGPUProcessConnectionDelayedReply&&);
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2021-04-16 18:41:22 UTC (rev 276148)
@@ -786,10 +786,10 @@
m_processPool->getGPUProcessConnection(*this, WTFMove(parameters), WTFMove(reply));
}
-void WebProcessProxy::gpuProcessCrashed()
+void WebProcessProxy::gpuProcessExited(GPUProcessTerminationReason reason)
{
for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
- page->gpuProcessCrashed();
+ page->gpuProcessExited(reason);
}
#endif
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -376,7 +376,7 @@
#endif
#if ENABLE(GPU_PROCESS)
- void gpuProcessCrashed();
+ void gpuProcessExited(GPUProcessTerminationReason);
#endif
bool hasSleepDisabler() const;
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -81,7 +81,7 @@
#endif // HAVE(VISIBILITY_PROPAGATION_VIEW)
#if ENABLE(GPU_PROCESS)
- void gpuProcessCrashed() override;
+ void gpuProcessDidExit() override;
#endif
void preferencesDidChange() override;
void toolTipChanged(const String&, const String&) override;
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2021-04-16 18:41:22 UTC (rev 276148)
@@ -212,9 +212,9 @@
#endif // HAVE(VISIBILITY_PROPAGATION_VIEW)
#if ENABLE(GPU_PROCESS)
-void PageClientImpl::gpuProcessCrashed()
+void PageClientImpl::gpuProcessDidExit()
{
- [m_contentView _gpuProcessCrashed];
+ [m_contentView _gpuProcessDidExit];
}
#endif
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentView.h (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/ios/WKContentView.h 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentView.h 2021-04-16 18:41:22 UTC (rev 276148)
@@ -98,7 +98,7 @@
- (std::unique_ptr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy:(WebKit::WebProcessProxy&)process;
- (void)_processDidExit;
#if ENABLE(GPU_PROCESS)
-- (void)_gpuProcessCrashed;
+- (void)_gpuProcessDidExit;
#endif
- (void)_processWillSwap;
- (void)_didRelaunchProcess;
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentView.mm (276147 => 276148)
--- trunk/Source/WebKit/UIProcess/ios/WKContentView.mm 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentView.mm 2021-04-16 18:41:22 UTC (rev 276148)
@@ -656,7 +656,7 @@
}
#if ENABLE(GPU_PROCESS)
-- (void)_gpuProcessCrashed
+- (void)_gpuProcessDidExit
{
#if HAVE(VISIBILITY_PROPAGATION_VIEW)
[self _removeVisibilityPropagationViewForGPUProcess];
Modified: trunk/Tools/ChangeLog (276147 => 276148)
--- trunk/Tools/ChangeLog 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Tools/ChangeLog 2021-04-16 18:41:22 UTC (rev 276148)
@@ -1,3 +1,16 @@
+2021-04-16 Chris Dumez <[email protected]>
+
+ Exit the GPUProcess when under memory pressure if it is not being used
+ https://bugs.webkit.org/show_bug.cgi?id=224556
+
+ Reviewed by Darin Adler.
+
+ Add API test coverage.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
+ (runMemoryPressureExitTest):
+ (TEST):
+
2021-04-16 Aakash Jain <[email protected]>
[ews] Improve step description when layout-tests step is skipped
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm (276147 => 276148)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm 2021-04-16 18:17:21 UTC (rev 276147)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm 2021-04-16 18:41:22 UTC (rev 276148)
@@ -34,6 +34,8 @@
#import <WebKit/WKString.h>
#import <WebKit/WKWebViewConfiguration.h>
#import <WebKit/WKWebViewPrivate.h>
+#import <notify.h>
+#import <wtf/Function.h>
#import <wtf/RetainPtr.h>
#if PLATFORM(MAC)
@@ -490,3 +492,90 @@
}];
TestWebKitAPI::Util::run(&done);
}
+
+static void runMemoryPressureExitTest(Function<void(WKWebView *)>&& loadTestPageSynchronously)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("UseGPUProcessForMediaEnabled"));
+ WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("CaptureVideoInGPUProcessEnabled"));
+ WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("UseGPUProcessForCanvasRenderingEnabled"));
+ WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], false, WKStringCreateWithUTF8CString("UseGPUProcessForDOMRenderingEnabled"));
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
+ loadTestPageSynchronously(webView.get());
+
+ // A GPUProcess should get launched.
+ while (![configuration.get().processPool _gpuProcessIdentifier])
+ TestWebKitAPI::Util::sleep(0.1);
+ auto gpuProcessPID = [configuration.get().processPool _gpuProcessIdentifier];
+
+ // Simulate memory pressure (notifyutil -p org.WebKit.lowMemory).
+ notify_post("org.WebKit.lowMemory");
+
+ // Make sure the GPUProcess does not exit since it is still needed.
+ TestWebKitAPI::Util::sleep(0.5);
+ EXPECT_EQ(gpuProcessPID, [configuration.get().processPool _gpuProcessIdentifier]);
+
+ // Navigate to another page that no longer requires the GPUProcess.
+ [webView synchronouslyLoadTestPageNamed:@"simple"];
+
+ // The GPUProcess should exit on memory pressure.
+ do {
+ // Simulate memory pressure (notifyutil -p org.WebKit.lowMemory).
+ notify_post("org.WebKit.lowMemory");
+ TestWebKitAPI::Util::sleep(0.1);
+ } while ([configuration.get().processPool _gpuProcessIdentifier]);
+
+ // The GPUProcess should not relaunch.
+ TestWebKitAPI::Util::sleep(0.5);
+ EXPECT_EQ(0, [configuration.get().processPool _gpuProcessIdentifier]);
+}
+
+TEST(GPUProcess, ExitsUnderMemoryPressureCanvasCase)
+{
+ runMemoryPressureExitTest([](WKWebView *webView) {
+ [webView synchronouslyLoadHTMLString:testCanvasPage];
+
+ __block bool done = false;
+ [webView evaluateJavaScript:@"context.fillStyle = '#00FF00'; context.fillRect(0, 0, 400, 400);" completionHandler:^(id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+ [webView evaluateJavaScript:@"context.getImageData(0, 0, 400, 400).width" completionHandler:^(id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ });
+}
+
+TEST(GPUProcess, ExitsUnderMemoryPressureVideoCase)
+{
+ runMemoryPressureExitTest([](WKWebView *webView) {
+ [webView synchronouslyLoadTestPageNamed:@"large-videos-with-audio"];
+
+ __block bool done = false;
+ [webView evaluateJavaScript:@"document.getElementsByTagName('video')[0].play() && true" completionHandler:^(id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ });
+}
+
+TEST(GPUProcess, ExitsUnderMemoryPressureWebAudioCase)
+{
+ runMemoryPressureExitTest([](WKWebView *webView) {
+ [webView synchronouslyLoadTestPageNamed:@"audio-context-playing"];
+
+ // evaluateJavaScript gives us the user gesture we need to reliably start audio playback on all platforms.
+ __block bool done = false;
+ [webView evaluateJavaScript:@"startPlaying()" completionHandler:^(id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+ });
+}