RESOLVED FIXED 224533
[GTK][WPE] Properly recover from unresponsive web processes
https://bugs.webkit.org/show_bug.cgi?id=224533
Summary [GTK][WPE] Properly recover from unresponsive web processes
Miguel Gomez
Reported 2021-04-14 00:41:56 PDT
Bug 224359 added a signal to WebKitWebView to indicate whether the web process associated to it has become unresponsive. But currently the only way to recover from that scenario is by recreating the view, as the other methods that could be useful (reload, uri or load alternate html) will hang if the web process is not responsive. We need to look into those to make them work in that scenario.
Attachments
Patch (16.13 KB, patch)
2021-04-29 09:51 PDT, Miguel Gomez
no flags
Patch (15.93 KB, patch)
2021-04-30 01:59 PDT, Miguel Gomez
no flags
Patch (15.66 KB, patch)
2021-04-30 02:42 PDT, Miguel Gomez
no flags
Patch (15.75 KB, patch)
2021-04-30 06:01 PDT, Miguel Gomez
no flags
Patch (15.66 KB, patch)
2021-04-30 08:07 PDT, Miguel Gomez
no flags
Fujii Hironori
Comment 1 2021-04-28 00:38:54 PDT
You can get the pid of the web process by using WKPageGetProcessIdentifier API. You can kill the unresponsive web process. I am not sure this is the proper way to recover.
Miguel Gomez
Comment 2 2021-04-28 01:16:08 PDT
(In reply to Fujii Hironori from comment #1) > You can get the pid of the web process by using WKPageGetProcessIdentifier > API. You can kill the unresponsive web process. I am not sure this is the > proper way to recover. I think that's the intended way to do it when using the C API (I know some people are doing it that way). In the glib API we don't have an equivalent to WKPageGetProcessIdentifier though. We could add one and follow the same approach, or we could just add an API method to WebKitWebView to directly kill the web content process.
Michael Catanzaro
Comment 3 2021-04-28 06:12:23 PDT
(In reply to Miguel Gomez from comment #2) > or we could just add > an API method to WebKitWebView to directly kill the web content process. That seems like a better approach, but I'm not convinced it's needed. webkit_web_view_load_* could do the killing for us internally.
Carlos Garcia Campos
Comment 4 2021-04-29 00:49:34 PDT
My initial idea was to implicitly kill the web process if it's unresponsive when new load happens or on refresh, but now I'm more convinced that an explicit approach would be better. It might not be obvious for the user that a new load needs to happen, for example. In the case of a crash we don't have a web process anymore, so a new load is no different than the initial load. And we probably only want to kill the process if the user handled the signal, but it's a property notification so we don't really know what the user replied. If we decide to go with the explicit approach I would expose a method to kill the web view web process, I wouldn't expose process ids.
Miguel Gomez
Comment 5 2021-04-29 09:51:18 PDT
EWS Watchlist
Comment 6 2021-04-29 09:52:23 PDT
Thanks for the patch. If this patch contains new public API please make sure it follows the guidelines for new WebKit2 GTK+ API. See https://trac.webkit.org/wiki/WebKitGTK/AddingNewWebKit2API
Michael Catanzaro
Comment 7 2021-04-29 10:29:27 PDT
Comment on attachment 427352 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=427352&action=review LGTM > Source/WebKit/UIProcess/API/glib/WebKitNavigationClient.cpp:121 > + case ProcessTerminationReason::ExceededCPULimit: Preexisting problem: this one should use WEBKIT_WEB_PROCESS_CRASHED (or ideally get its own public enum value). The other three cases occur when the process is terminated due to implementation detail, so it makes sense that the application is not notified. But exceeded CPU limit is definitely something the application needs to know about in order to offer the process crash error page. > Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp:4780 > + if (auto* provisionalPageProxy = page.provisionalPageProxy()) { > + Ref<WebKit::WebProcessProxy> protectedProcessProxy(provisionalPageProxy->process()); > + protectedProcessProxy->requestTermination(WebKit::ProcessTerminationReason::RequestedByClient); > + } Hmm... do we really want to kill the provisional page? I'm not entirely sure what the provisional page is, but my guess is that is the prewarmed process that is waiting to be swapped in. If so, we don't want to kill it, as it's not unresponsive, and that would slow down the process swap that's about to occur. Am I wrong? > Source/WebKit/UIProcess/API/gtk/WebKitWebView.h:196 > + * @WEBKIT_WEB_PROCESS_REQUESTED_BY_API: the web process termination was requested by an API call. @WEBKIT_WEB_PROCESS_REQUESTED_BY_API: the web process termination was requested by an API call. Since: 2.34 > Source/WebKit/UIProcess/API/wpe/WebKitWebView.h:165 > + * @WEBKIT_WEB_PROCESS_REQUESTED_BY_API: the web process termination was requested by an API call. @WEBKIT_WEB_PROCESS_REQUESTED_BY_API: the web process termination was requested by an API call. Since: 2.34 > Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:1551 > + static gboolean webProcessTerminatedCallback(WebKitWebView *webView, WebKitWebProcessTerminationReason reason, WebViewTerminateWebProcessTest* test) This should return void, not gboolean, since the web-process-terminated signal has no return value. Also the * is hanging wrong: WebKitWebView* webView > Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:1586 > + " setTimeout(function() {" > + " var start = new Date().getTime();" > + " var end = start;" > + " while(end < start + 4000) {" > + " end = new Date().getTime();" > + " }" > + " }, 500);" I think you could just do while(true) in the timeout callback.
Michael Catanzaro
Comment 8 2021-04-29 10:31:25 PDT
(In reply to Michael Catanzaro from comment #7) > Hmm... do we really want to kill the provisional page? I'm not entirely sure > what the provisional page is, but my guess is that is the prewarmed process > that is waiting to be swapped in. If so, we don't want to kill it, as it's > not unresponsive, and that would slow down the process swap that's about to > occur. Am I wrong? Hm, maybe it is a page that's used during provisional loads before the load is committed? Then killing it is needed in case it is unresponsive?
Carlos Garcia Campos
Comment 9 2021-04-30 00:40:55 PDT
Comment on attachment 427352 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=427352&action=review >> Source/WebKit/UIProcess/API/glib/WebKitNavigationClient.cpp:121 >> + case ProcessTerminationReason::ExceededCPULimit: > > Preexisting problem: this one should use WEBKIT_WEB_PROCESS_CRASHED (or ideally get its own public enum value). The other three cases occur when the process is terminated due to implementation detail, so it makes sense that the application is not notified. But exceeded CPU limit is definitely something the application needs to know about in order to offer the process crash error page. We don't have CPU limit enabled, only memory limit. I agree we should enable it and then expose the option, but that should be a separate bug. >> Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp:4780 >> + } > > Hmm... do we really want to kill the provisional page? I'm not entirely sure what the provisional page is, but my guess is that is the prewarmed process that is waiting to be swapped in. If so, we don't want to kill it, as it's not unresponsive, and that would slow down the process swap that's about to occur. Am I wrong? This is what cocoa does
Miguel Gomez
Comment 10 2021-04-30 01:59:27 PDT
Carlos Garcia Campos
Comment 11 2021-04-30 02:09:58 PDT
Comment on attachment 427401 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=427401&action=review > Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp:4763 > + * signal is emitted with WEBKIT_WEB_PROCESS_REQUESTED_BY_API as the reason for WEBKIT_WEB_PROCESS_REQUESTED_BY_API -> %WEBKIT_WEB_PROCESS_REQUESTED_BY_API > Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:1561 > + g_signal_connect_after(test->m_webView, "web-process-terminated", G_CALLBACK(WebViewTerminateWebProcessTest::webProcessTerminatedCallback), test); I would connect to the signal from the WebViewTerminateWebProcessTest constructor > Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:1570 > + g_signal_handlers_disconnect_by_func(test->m_webView, reinterpret_cast<void*>(WebViewTerminateWebProcessTest::webProcessTerminatedCallback), test); And disconnect from the destructor using g_signal_handlers_disconnect_by_data > Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:1586 > + g_signal_connect_after(test->m_webView, "web-process-terminated", G_CALLBACK(WebViewTerminateWebProcessTest::webProcessTerminatedCallback), test); Ditto. > Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:1606 > + g_signal_handlers_disconnect_by_func(test->m_webView, reinterpret_cast<void*>(WebViewTerminateWebProcessTest::webProcessTerminatedCallback), test); Ditto.
Miguel Gomez
Comment 12 2021-04-30 02:42:51 PDT
Michael Catanzaro
Comment 13 2021-04-30 05:16:29 PDT
Comment on attachment 427403 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=427403&action=review OK, nice. > Source/WebKit/UIProcess/API/gtk/WebKitWebView.h:196 > + * @WEBKIT_WEB_PROCESS_REQUESTED_BY_API: the web process termination was requested by an API call. Since: 2.34 Let's call it WEBKIT_WEB_PROCESS_TERMINATION_REQUESTED_BY_API or WEBKIT_WEB_PROCESS_KILL_REQUESTED_BY_API
Miguel Gomez
Comment 14 2021-04-30 06:01:59 PDT
Adrian Perez
Comment 15 2021-04-30 06:32:26 PDT
(In reply to Michael Catanzaro from comment #13) > Comment on attachment 427403 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=427403&action=review > > OK, nice. > > > Source/WebKit/UIProcess/API/gtk/WebKitWebView.h:196 > > + * @WEBKIT_WEB_PROCESS_REQUESTED_BY_API: the web process termination was requested by an API call. Since: 2.34 > > Let's call it WEBKIT_WEB_PROCESS_TERMINATION_REQUESTED_BY_API or > WEBKIT_WEB_PROCESS_KILL_REQUESTED_BY_API Gah! Such a mouthful. How about WEBKIT_WEB_PROCESS_API_TERMINATION, which is two words less? :)
Carlos Garcia Campos
Comment 16 2021-04-30 07:18:24 PDT
WEBKIT_WEB_PROCESS_TERMINATED_BY_API
Miguel Gomez
Comment 17 2021-04-30 08:07:25 PDT
Michael Catanzaro
Comment 18 2021-04-30 08:36:31 PDT
(In reply to Carlos Garcia Campos from comment #16) > WEBKIT_WEB_PROCESS_TERMINATED_BY_API Good name.
EWS
Comment 19 2021-04-30 11:58:11 PDT
Committed r276848 (237199@main): <https://commits.webkit.org/237199@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 427419 [details].
Note You need to log in before you can comment on or make changes to this bug.