Title: [276848] trunk
Revision
276848
Author
[email protected]
Date
2021-04-30 11:58:03 -0700 (Fri, 30 Apr 2021)

Log Message

[GTK][WPE] Properly recover from unresponsive web processes
https://bugs.webkit.org/show_bug.cgi?id=224533

Reviewed by Carlos Garcia Campos.

Source/WebKit:

Add a new method to the GLib API to terminate the web process associated to a
WebKitWebView.

* UIProcess/API/glib/WebKitNavigationClient.cpp:
* UIProcess/API/glib/WebKitWebView.cpp:
(webkit_web_view_terminate_web_process):
* UIProcess/API/gtk/WebKitWebView.h:
* UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
* UIProcess/API/wpe/WebKitWebView.h:
* UIProcess/API/wpe/docs/wpe-1.0-sections.txt:

Tools:

Add unit tests for the new webkit_web_view_terminate_web_process GLib API method. Also move
the methods used to wait for responsiveness changes to WebViewTest, as they are used by more
than a single test.

* TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:
(testWebViewIsWebProcessResponsive):
(testWebViewTerminateWebProcess):
(testWebViewTerminateUnresponsiveWebProcess):
(beforeAll):
* TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp:
(isWebProcessResponsiveChanged):
(WebViewTest::waitUntilIsWebProcessResponsiveChanged):
* TestWebKitAPI/glib/WebKitGLib/WebViewTest.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (276847 => 276848)


--- trunk/Source/WebKit/ChangeLog	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Source/WebKit/ChangeLog	2021-04-30 18:58:03 UTC (rev 276848)
@@ -1,3 +1,21 @@
+2021-04-30  Miguel Gomez  <[email protected]>
+
+        [GTK][WPE] Properly recover from unresponsive web processes
+        https://bugs.webkit.org/show_bug.cgi?id=224533
+
+        Reviewed by Carlos Garcia Campos.
+
+        Add a new method to the GLib API to terminate the web process associated to a
+        WebKitWebView.
+
+        * UIProcess/API/glib/WebKitNavigationClient.cpp:
+        * UIProcess/API/glib/WebKitWebView.cpp:
+        (webkit_web_view_terminate_web_process):
+        * UIProcess/API/gtk/WebKitWebView.h:
+        * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
+        * UIProcess/API/wpe/WebKitWebView.h:
+        * UIProcess/API/wpe/docs/wpe-1.0-sections.txt:
+
 2021-04-30  Per Arne  <[email protected]>
 
         Enforce IOKit filtering

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitNavigationClient.cpp (276847 => 276848)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitNavigationClient.cpp	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitNavigationClient.cpp	2021-04-30 18:58:03 UTC (rev 276848)
@@ -115,8 +115,10 @@
         case ProcessTerminationReason::ExceededMemoryLimit:
             webkitWebViewWebProcessTerminated(m_webView, WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT);
             return true;
+        case ProcessTerminationReason::RequestedByClient:
+            webkitWebViewWebProcessTerminated(m_webView, WEBKIT_WEB_PROCESS_TERMINATED_BY_API);
+            return true;
         case ProcessTerminationReason::ExceededCPULimit:
-        case ProcessTerminationReason::RequestedByClient:
         case ProcessTerminationReason::RequestedByNetworkProcess:
         case ProcessTerminationReason::NavigationSwap:
         case ProcessTerminationReason::RequestedByGPUProcess:

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp (276847 => 276848)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2021-04-30 18:58:03 UTC (rev 276848)
@@ -28,6 +28,7 @@
 #include "APISerializedScriptValue.h"
 #include "DataReference.h"
 #include "ImageOptions.h"
+#include "ProvisionalPageProxy.h"
 #include "WebCertificateInfo.h"
 #include "WebContextMenuItem.h"
 #include "WebContextMenuItemData.h"
@@ -4752,3 +4753,31 @@
 
     return webView->priv->isWebProcessResponsive;
 }
+
+/**
+ * webkit_web_view_terminate_web_process:
+ * @web_view: a #WebKitWebView
+ *
+ * Terminates the web process associated to @web_view. When the web process gets terminated
+ * using this method, the #WebKitWebView::web-process-terminated signal is emitted with
+ * %WEBKIT_WEB_PROCESS_TERMINATED_BY_API as the reason for termination.
+ *
+ * Since: 2.34
+ */
+void webkit_web_view_terminate_web_process(WebKitWebView* webView)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
+
+    auto& page = getPage(webView);
+
+    Ref<WebKit::WebProcessProxy> protectedProcessProxy(page.process());
+    protectedProcessProxy->requestTermination(WebKit::ProcessTerminationReason::RequestedByClient);
+
+    if (auto* provisionalPageProxy = page.provisionalPageProxy()) {
+        Ref<WebKit::WebProcessProxy> protectedProcessProxy(provisionalPageProxy->process());
+        protectedProcessProxy->requestTermination(WebKit::ProcessTerminationReason::RequestedByClient);
+    }
+
+    // Reset the state of the responsiveness property.
+    webkitWebViewSetIsWebProcessResponsive(webView, true);
+}

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebView.h (276847 => 276848)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebView.h	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebView.h	2021-04-30 18:58:03 UTC (rev 276848)
@@ -193,6 +193,7 @@
  * WebKitWebProcessTerminationReason:
  * @WEBKIT_WEB_PROCESS_CRASHED: the web process crashed.
  * @WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT: the web process exceeded the memory limit.
+ * @WEBKIT_WEB_PROCESS_TERMINATED_BY_API: the web process termination was requested by an API call. Since: 2.34
  *
  * Enum values used to specify the reason why the web process terminated abnormally.
  *
@@ -200,7 +201,8 @@
  */
 typedef enum {
     WEBKIT_WEB_PROCESS_CRASHED,
-    WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT
+    WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT,
+    WEBKIT_WEB_PROCESS_TERMINATED_BY_API
 } WebKitWebProcessTerminationReason;
 
 struct _WebKitWebView {
@@ -592,6 +594,9 @@
 WEBKIT_API gboolean
 webkit_web_view_get_is_web_process_responsive        (WebKitWebView             *web_view);
 
+WEBKIT_API void
+webkit_web_view_terminate_web_process                (WebKitWebView             *web_view);
+
 G_END_DECLS
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt (276847 => 276848)


--- trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt	2021-04-30 18:58:03 UTC (rev 276848)
@@ -291,6 +291,7 @@
 webkit_web_view_get_input_method_context
 webkit_web_view_get_website_policies
 webkit_web_view_get_is_web_process_responsive
+webkit_web_view_terminate_web_process
 
 <SUBSECTION WebKitJavascriptResult>
 WebKitJavascriptResult

Modified: trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebView.h (276847 => 276848)


--- trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebView.h	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebView.h	2021-04-30 18:58:03 UTC (rev 276848)
@@ -162,6 +162,7 @@
  * WebKitWebProcessTerminationReason:
  * @WEBKIT_WEB_PROCESS_CRASHED: the web process crashed.
  * @WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT: the web process exceeded the memory limit.
+ * @WEBKIT_WEB_PROCESS_TERMINATED_BY_API: the web process termination was requested by an API call. Since: 2.34
  *
  * Enum values used to specify the reason why the web process terminated abnormally.
  *
@@ -169,7 +170,8 @@
  */
 typedef enum {
     WEBKIT_WEB_PROCESS_CRASHED,
-    WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT
+    WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT,
+    WEBKIT_WEB_PROCESS_TERMINATED_BY_API
 } WebKitWebProcessTerminationReason;
 
 /**
@@ -568,6 +570,9 @@
 WEBKIT_API gboolean
 webkit_web_view_get_is_web_process_responsive        (WebKitWebView             *web_view);
 
+WEBKIT_API void
+webkit_web_view_terminate_web_process                (WebKitWebView             *web_view);
+
 G_END_DECLS
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt (276847 => 276848)


--- trunk/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt	2021-04-30 18:58:03 UTC (rev 276848)
@@ -263,6 +263,7 @@
 webkit_web_view_get_input_method_context
 webkit_web_view_get_website_policies
 webkit_web_view_get_is_web_process_responsive
+webkit_web_view_terminate_web_process
 
 <SUBSECTION WebKitJavascriptResult>
 WebKitJavascriptResult

Modified: trunk/Tools/ChangeLog (276847 => 276848)


--- trunk/Tools/ChangeLog	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Tools/ChangeLog	2021-04-30 18:58:03 UTC (rev 276848)
@@ -1,3 +1,24 @@
+2021-04-30  Miguel Gomez  <[email protected]>
+
+        [GTK][WPE] Properly recover from unresponsive web processes
+        https://bugs.webkit.org/show_bug.cgi?id=224533
+
+        Reviewed by Carlos Garcia Campos.
+
+        Add unit tests for the new webkit_web_view_terminate_web_process GLib API method. Also move
+        the methods used to wait for responsiveness changes to WebViewTest, as they are used by more
+        than a single test.
+
+        * TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:
+        (testWebViewIsWebProcessResponsive):
+        (testWebViewTerminateWebProcess):
+        (testWebViewTerminateUnresponsiveWebProcess):
+        (beforeAll):
+        * TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp:
+        (isWebProcessResponsiveChanged):
+        (WebViewTest::waitUntilIsWebProcessResponsiveChanged):
+        * TestWebKitAPI/glib/WebKitGLib/WebViewTest.h:
+
 2021-04-30  Jonathan Bedard  <[email protected]>
 
         [webkitpy] Support pickling platforminfo

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp (276847 => 276848)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp	2021-04-30 18:58:03 UTC (rev 276848)
@@ -1177,24 +1177,7 @@
     g_assert_cmpint(webkit_website_policies_get_autoplay_policy(policies), ==, WEBKIT_AUTOPLAY_ALLOW_WITHOUT_SOUND);
 }
 
-class WebViewIsWebProcessResponsiveTest: public WebViewTest {
-public:
-    MAKE_GLIB_TEST_FIXTURE(WebViewIsWebProcessResponsiveTest);
-
-    static void isWebProcessResponsiveChanged(WebKitWebView* view, GParamSpec*, WebViewIsWebProcessResponsiveTest* test)
-    {
-        g_signal_handlers_disconnect_by_func(test->m_webView, reinterpret_cast<void*>(isWebProcessResponsiveChanged), test);
-        g_main_loop_quit(test->m_mainLoop);
-    }
-
-    void waitUntilIsWebProcessResponsiveChanged()
-    {
-        g_signal_connect(m_webView, "notify::is-web-process-responsive", G_CALLBACK(isWebProcessResponsiveChanged), this);
-        g_main_loop_run(m_mainLoop);
-    }
-};
-
-static void testWebViewIsWebProcessResponsive(WebViewIsWebProcessResponsiveTest* test, gconstpointer)
+static void testWebViewIsWebProcessResponsive(WebViewTest* test, gconstpointer)
 {
     static const char* hangHTML =
         "<html>"
@@ -1561,6 +1544,70 @@
 }
 #endif
 
+class WebViewTerminateWebProcessTest: public WebViewTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(WebViewTerminateWebProcessTest);
+
+    static void webProcessTerminatedCallback(WebKitWebView* webView, WebKitWebProcessTerminationReason reason, WebViewTerminateWebProcessTest* test)
+    {
+        test->m_terminationReason = reason;
+    }
+
+    WebViewTerminateWebProcessTest()
+    {
+        g_signal_connect_after(m_webView, "web-process-terminated", G_CALLBACK(WebViewTerminateWebProcessTest::webProcessTerminatedCallback), this);
+    }
+
+    ~WebViewTerminateWebProcessTest()
+    {
+        g_signal_handlers_disconnect_by_data(m_webView, this);
+    }
+
+    WebKitWebProcessTerminationReason m_terminationReason { WEBKIT_WEB_PROCESS_CRASHED };
+};
+
+static void testWebViewTerminateWebProcess(WebViewTerminateWebProcessTest* test, gconstpointer)
+{
+    test->loadHtml("<html></html>", nullptr);
+    test->waitUntilLoadFinished();
+    test->m_expectedWebProcessCrash = true;
+    webkit_web_view_terminate_web_process(test->m_webView);
+    g_assert_cmpuint(test->m_terminationReason, ==, WEBKIT_WEB_PROCESS_TERMINATED_BY_API);
+    g_assert_true(webkit_web_view_get_is_web_process_responsive(test->m_webView));
+}
+
+static void testWebViewTerminateUnresponsiveWebProcess(WebViewTerminateWebProcessTest* test, gconstpointer)
+{
+    static const char* hangHTML =
+        "<html>"
+        " <body>"
+        "  <script>"
+        "   setTimeout(function() {"
+        "     while(true) { }"
+        "    }, 500);"
+        "  </script>"
+        " </body>"
+        "</html>";
+
+    test->loadHtml(hangHTML, nullptr);
+    test->waitUntilLoadFinished();
+    g_assert_true(webkit_web_view_get_is_web_process_responsive(test->m_webView));
+    // Wait 1 second, so the js while loop kicks in and blocks the web process, and try to load a new page.
+    // As the web process is busy this won't work, and after 3 seconds the web process will be marked
+    // as unresponsive.
+    test->wait(1);
+    test->loadHtml("<html></html>", nullptr);
+    test->waitUntilIsWebProcessResponsiveChanged();
+    g_assert_false(webkit_web_view_get_is_web_process_responsive(test->m_webView));
+
+    // Now that the process is unresponsive, terminate it.
+    test->m_expectedWebProcessCrash = true;
+    test->m_terminationReason = WEBKIT_WEB_PROCESS_CRASHED;
+    webkit_web_view_terminate_web_process(test->m_webView);
+    g_assert_cmpuint(test->m_terminationReason, ==, WEBKIT_WEB_PROCESS_TERMINATED_BY_API);
+    g_assert_true(webkit_web_view_get_is_web_process_responsive(test->m_webView));
+}
+
 #if USE(SOUP2)
 static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
 #else
@@ -1628,7 +1675,9 @@
 #if PLATFORM(WPE) && USE(WPEBACKEND_FDO_AUDIO_EXTENSION)
     AudioRenderingWebViewTest::add("WebKitWebView", "external-audio-rendering", testWebViewExternalAudioRendering);
 #endif
-    WebViewIsWebProcessResponsiveTest::add("WebKitWebView", "is-web-process-responsive", testWebViewIsWebProcessResponsive);
+    WebViewTest::add("WebKitWebView", "is-web-process-responsive", testWebViewIsWebProcessResponsive);
+    WebViewTerminateWebProcessTest::add("WebKitWebView", "terminate-web-process", testWebViewTerminateWebProcess);
+    WebViewTerminateWebProcessTest::add("WebKitWebView", "terminate-unresponsive-web-process", testWebViewTerminateUnresponsiveWebProcess);
 }
 
 void afterAll()

Modified: trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp (276847 => 276848)


--- trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp	2021-04-30 18:58:03 UTC (rev 276848)
@@ -223,6 +223,18 @@
     waitUntilTitleChangedTo(0);
 }
 
+static void isWebProcessResponsiveChanged(WebKitWebView* webView, GParamSpec*, WebViewTest* test)
+{
+    g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(isWebProcessResponsiveChanged), test);
+    g_main_loop_quit(test->m_mainLoop);
+}
+
+void WebViewTest::waitUntilIsWebProcessResponsiveChanged()
+{
+    g_signal_connect(m_webView, "notify::is-web-process-responsive", G_CALLBACK(isWebProcessResponsiveChanged), this);
+    g_main_loop_run(m_mainLoop);
+}
+
 void WebViewTest::selectAll()
 {
     webkit_web_view_execute_editing_command(m_webView, "SelectAll");

Modified: trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.h (276847 => 276848)


--- trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.h	2021-04-30 18:39:44 UTC (rev 276847)
+++ trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.h	2021-04-30 18:58:03 UTC (rev 276848)
@@ -53,6 +53,7 @@
     void waitUntilTitleChangedTo(const char* expectedTitle);
     void waitUntilTitleChanged();
     void waitUntilFileChanged(const char*, GFileMonitorEvent);
+    void waitUntilIsWebProcessResponsiveChanged();
     void resizeView(int width, int height);
     void hideView();
     void selectAll();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to