From f6f4d72c2769ddb8b63fa5986bc70f5427d214ee Mon Sep 17 00:00:00 2001 From: Kimmo Kinnunen Date: Thu, 15 Aug 2024 02:27:49 -0700 Subject: [PATCH] GPU process is terminated during debugging https://bugs.webkit.org/show_bug.cgi?id=277731 rdar://133372529 Reviewed by Mike Wyrzykowski. GPU process would not be debuggable due to WCP timing out a send or wait to GPUP. This would cause following distinct problems - WCP would ask UI to terminate GPUP - Even if GPUP was not terminated, the WCP would already be in undefined state due to timing out a send or a wait. Add a setting ChildProcessDebuggabilityEnabled which should be set when the developer is intending to stop the GPU process in debugger. The added implementation will set stream IPC connection timeout to infinity. Later commits will modify other, less frequent normal IPC sendSync and wait timeouts. Run with: lldb -w -n GPU.Development -o c run-webkit-tests --internal-feature=ChildProcessDebuggabilityEnabled --no-timeout test.html run-minibrowser Set "Internal -> Child Process Debuggability" and restart * Source/WTF/Scripts/GeneratePreferences.rb: * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: * Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp: (WebKit::RemoteGraphicsContextGLProxy::create): * Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp: (WebKit::RemoteRenderingBackendProxy::ensureGPUProcessConnection): * Source/WebKit/WebProcess/GPU/graphics/WebGPU/RemoteGPUProxy.cpp: (WebKit::RemoteGPUProxy::create): * Source/WebKit/WebProcess/WebPage/WebPage.cpp: (WebKit::WebPage::updatePreferences): * Source/WebKit/WebProcess/WebProcess.cpp: (WebKit::WebProcess::gpuProcessTimeoutDuration const): (WebKit::WebProcess::setGPUProcessDebuggabilityEnabled): * Source/WebKit/WebProcess/WebProcess.h: Canonical link: https://commits.webkit.org/282280@main --- Introduction.md | 7 ++++++- .../Preferences/UnifiedWebPreferences.yaml | 15 +++++++++++++++ .../GPU/graphics/RemoteGraphicsContextGLProxy.cpp | 3 +-- .../GPU/graphics/RemoteRenderingBackendProxy.cpp | 4 ++-- .../GPU/graphics/WebGPU/RemoteGPUProxy.cpp | 3 +-- Source/WebKit/WebProcess/WebPage/WebPage.cpp | 2 ++ Source/WebKit/WebProcess/WebProcess.cpp | 11 +++++++++++ Source/WebKit/WebProcess/WebProcess.h | 6 ++++++ 8 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Introduction.md b/Introduction.md index a73b246c92941..2bdfa50e208eb 100644 --- a/Introduction.md +++ b/Introduction.md @@ -202,6 +202,10 @@ When debugging a debug build in LLDB, there are also a few functions that can be * showTreeForThis() * showNodePathForThis() +Debugging child processes such as GPU process, "Child Process Debuggability" internal feature must be in use. For the test runner, you can +specify `run-webkit-tests --internal-feature=ChildProcessDebuggabilityEnabled`. For MiniBrowser, set the Debug > Internal > Child Process Debuggability +menu item and restart. + ## Correctness Testing in WebKit WebKit is really big on test driven development, we have many types of tests. @@ -1759,7 +1763,8 @@ You may want to specify OS_ACTIVITY_MODE environmental variable to “disable” in order to suppress all the system logging that happens during the debugging session. You may also want to specify `--no-timeout` option to prevent WebKitTestRunner or DumpRenderTree -to stop the test after 30 seconds if you’re stepping through code. +to stop the test after 30 seconds if you’re stepping through code. Specify additional +`--internal-feature=ChildProcessDebuggabilityEnabled` when stepping through child process such as GPU process. Once this is done, you can run WebKitTestRunner or DumpRenderTree by going to Product > Perform Action > Run without Building. diff --git a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml index dbf141d21562d..ec7dfa4ea4d88 100644 --- a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml +++ b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml @@ -1707,6 +1707,21 @@ CaretBrowsingEnabled: WebCore: default: false +ChildProcessDebuggabilityEnabled: + comment: Disables GPU process IPC timeouts + type: bool + status: internal + humanReadableName: "Child Process Debuggability" + humanReadableDescription: "Enable stopping child processes with a debugger" + exposed: [ WebKit ] + defaultValue: + WebKitLegacy: + default: false + WebKit: + default: false + WebCore: + default: false + ClearSiteDataHTTPHeaderEnabled: type: bool status: stable diff --git a/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp b/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp index d13f190c7ab37..c8218a66792ae 100644 --- a/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp +++ b/Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp @@ -81,10 +81,9 @@ RefPtr RemoteGraphicsContextGLProxy::create(const { constexpr unsigned defaultConnectionBufferSizeLog2 = 21; unsigned connectionBufferSizeLog2 = defaultConnectionBufferSizeLog2; - constexpr Seconds defaultTimeoutDuration = 30_s; if (attributes.failContextCreationForTesting == WebCore::GraphicsContextGLAttributes::SimulatedCreationFailure::IPCBufferOOM) connectionBufferSizeLog2 = 50; // Expect this to fail. - auto connectionPair = IPC::StreamClientConnection::create(connectionBufferSizeLog2, defaultTimeoutDuration); + auto connectionPair = IPC::StreamClientConnection::create(connectionBufferSizeLog2, WebProcess::singleton().gpuProcessTimeoutDuration()); if (!connectionPair) return nullptr; auto [clientConnection, serverConnectionHandle] = WTFMove(*connectionPair); diff --git a/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp b/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp index 374ff174e9175..4fe64058e3cb1 100644 --- a/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp +++ b/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp @@ -102,8 +102,8 @@ void RemoteRenderingBackendProxy::ensureGPUProcessConnection() { if (m_connection) return; - static constexpr auto connectionBufferSizeLog2 = 21; - auto connectionPair = IPC::StreamClientConnection::create(connectionBufferSizeLog2, defaultTimeout); + constexpr unsigned connectionBufferSizeLog2 = 21u; + auto connectionPair = IPC::StreamClientConnection::create(connectionBufferSizeLog2, WebProcess::singleton().gpuProcessTimeoutDuration()); if (!connectionPair) CRASH(); auto [streamConnection, serverHandle] = WTFMove(*connectionPair); diff --git a/Source/WebKit/WebProcess/GPU/graphics/WebGPU/RemoteGPUProxy.cpp b/Source/WebKit/WebProcess/GPU/graphics/WebGPU/RemoteGPUProxy.cpp index 7f60adf8d01c8..c24dfcf606692 100644 --- a/Source/WebKit/WebProcess/GPU/graphics/WebGPU/RemoteGPUProxy.cpp +++ b/Source/WebKit/WebProcess/GPU/graphics/WebGPU/RemoteGPUProxy.cpp @@ -57,8 +57,7 @@ RefPtr RemoteGPUProxy::create(WebGPU::ConvertToBackingContext& c RefPtr RemoteGPUProxy::create(WebGPU::ConvertToBackingContext& convertToBackingContext, RemoteRenderingBackendProxy& renderingBackend, SerialFunctionDispatcher& dispatcher) { constexpr size_t connectionBufferSizeLog2 = 21; - constexpr Seconds defaultTimeoutDuration = 30_s; - auto connectionPair = IPC::StreamClientConnection::create(connectionBufferSizeLog2, defaultTimeoutDuration); + auto connectionPair = IPC::StreamClientConnection::create(connectionBufferSizeLog2, WebProcess::singleton().gpuProcessTimeoutDuration()); if (!connectionPair) return nullptr; auto [clientConnection, serverConnectionHandle] = WTFMove(*connectionPair); diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp index cab54b221c613..00ab406d1c456 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp +++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp @@ -4701,6 +4701,8 @@ void WebPage::updatePreferences(const WebPreferencesStore& store) if (m_drawingArea) m_drawingArea->updatePreferences(store); + WebProcess::singleton().setChildProcessDebuggabilityEnabled(store.getBoolValueForKey(WebPreferencesKey::childProcessDebuggabilityEnabledKey())); + #if ENABLE(GPU_PROCESS) static_cast(platformStrategies()->mediaStrategy()).setUseGPUProcess(m_shouldPlayMediaInGPUProcess); #if ENABLE(VIDEO) diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp index 7dac4718f46e3..16bc6bbd96420 100644 --- a/Source/WebKit/WebProcess/WebProcess.cpp +++ b/Source/WebKit/WebProcess/WebProcess.cpp @@ -1377,6 +1377,12 @@ GPUProcessConnection& WebProcess::ensureGPUProcessConnection() return *m_gpuProcessConnection; } +Seconds WebProcess::gpuProcessTimeoutDuration() const +{ + constexpr Seconds defaultTimeoutDuration = 15_s; + return m_childProcessDebuggabilityEnabled ? Seconds::infinity() : defaultTimeoutDuration; +} + void WebProcess::gpuProcessConnectionClosed() { ASSERT(m_gpuProcessConnection); @@ -2212,6 +2218,11 @@ void WebProcess::updateDomainsWithStorageAccessQuirks(HashSet m_accessibilityRemoteFrameTokenCache; #endif + bool m_childProcessDebuggabilityEnabled { false }; + #if ENABLE(GPU_PROCESS) bool m_useGPUProcessForCanvasRendering { false }; bool m_useGPUProcessForDOMRendering { false };