WebContent: Terminate immediately on client disconnect
Use Core::Process::terminate_immediately() when the UI process goes away or a sync IPC request fails because the client disconnected. This avoids running exit-time destructors during WebContent shutdown. Enable -Wexit-time-destructors for the WebContent executable and service target, then convert the existing warning sites to permanent process lifetime storage.
This commit is contained in:
parent
164ed80244
commit
26de1ca600
6 changed files with 41 additions and 21 deletions
|
|
@ -34,10 +34,12 @@ target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${LADYBIRD
|
|||
target_link_libraries(webcontentservice PUBLIC LibCore LibCrypto LibFileSystem LibGfx LibHTTP LibIPC LibJS LibMain LibMedia LibWasm LibWeb LibWebSocket LibRequests LibWebView LibImageDecoderClient LibGC)
|
||||
target_link_libraries(webcontentservice PRIVATE OpenSSL::Crypto OpenSSL::SSL)
|
||||
target_link_libraries(webcontentservice PRIVATE SDL3::SDL3)
|
||||
target_compile_options(webcontentservice PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Wexit-time-destructors>)
|
||||
|
||||
add_executable(WebContent main.cpp)
|
||||
|
||||
target_link_libraries(WebContent PRIVATE webcontentservice LibURL)
|
||||
target_compile_options(WebContent PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Wexit-time-destructors>)
|
||||
|
||||
if(WIN32)
|
||||
ladybird_windows_bin(WebContent CONSOLE)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <AK/JsonObject.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <LibCore/Process.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <LibGC/Heap.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
|
|
@ -100,7 +101,7 @@ void ConnectionFromClient::did_destroy_compositor_context(Web::Compositor::Compo
|
|||
|
||||
void ConnectionFromClient::die()
|
||||
{
|
||||
_exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
|
||||
Messages::WebContentServer::InitTransportResponse ConnectionFromClient::init_transport([[maybe_unused]] int peer_pid)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <AK/JsonObjectSerializer.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/Math.h>
|
||||
#include <LibCore/Process.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/ShareableBitmap.h>
|
||||
|
|
@ -605,7 +606,7 @@ HTTP::Cookie::VersionedCookie PageClient::page_did_request_cookie(URL::URL const
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestCookie>(m_id, url, source);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidRequestCookie. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
return response->take_cookie();
|
||||
}
|
||||
|
|
@ -615,7 +616,7 @@ void PageClient::page_did_set_cookie(URL::URL const& url, HTTP::Cookie::ParsedCo
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidSetCookie>(url, cookie, source);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidSetCookie. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -647,7 +648,7 @@ bool PageClient::page_did_is_known_hsts_host(String const& domain)
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidIsKnownHstsHost>(domain);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidIsKnownHstsHost. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
return response->result();
|
||||
}
|
||||
|
|
@ -657,7 +658,7 @@ Optional<String> PageClient::page_did_request_storage_item(Web::StorageAPI::Stor
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestStorageItem>(storage_endpoint, storage_key, bottle_key);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidRequestStorageItem. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
return response->take_value();
|
||||
}
|
||||
|
|
@ -667,7 +668,7 @@ WebView::StorageSetResult PageClient::page_did_set_storage_item(Web::StorageAPI:
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidSetStorageItem>(storage_endpoint, storage_key, bottle_key, value);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidSetStorageItem. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
return response->result();
|
||||
}
|
||||
|
|
@ -677,7 +678,7 @@ void PageClient::page_did_remove_storage_item(Web::StorageAPI::StorageEndpointTy
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRemoveStorageItem>(storage_endpoint, storage_key, bottle_key);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidRemoveStorageItem. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -686,7 +687,7 @@ Vector<String> PageClient::page_did_request_storage_keys(Web::StorageAPI::Storag
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestStorageKeys>(storage_endpoint, storage_key);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidRequestStorageKeys. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
return response->take_keys();
|
||||
}
|
||||
|
|
@ -696,7 +697,7 @@ void PageClient::page_did_clear_storage(Web::StorageAPI::StorageEndpointType sto
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidClearStorage>(storage_endpoint, storage_key);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidClearStorage. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -720,7 +721,7 @@ PageClient::NewWebViewResult PageClient::page_did_request_new_web_view(Web::HTML
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestNewWebView>(m_id, activate_tab, hints);
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during DidRequestNewWebView. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
|
||||
auto& new_client = m_owner.create_page(response->new_page_id());
|
||||
|
|
@ -819,7 +820,7 @@ Web::HTML::WorkerAgentId PageClient::start_worker_agent(Web::HTML::WorkerAgentSt
|
|||
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::StartWorkerAgent>(m_id, move(request));
|
||||
if (!response) {
|
||||
dbgln("WebContent client disconnected during StartWorkerAgent. Exiting peacefully.");
|
||||
exit(0);
|
||||
Core::Process::terminate_immediately(0);
|
||||
}
|
||||
|
||||
return response->agent_id();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <AK/NeverDestroyed.h>
|
||||
#include <AK/Time.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibCore/File.h>
|
||||
|
|
@ -2667,11 +2668,11 @@ ErrorOr<void, Web::WebDriver::Error> WebDriverConnection::ensure_current_top_lev
|
|||
// https://w3c.github.io/webdriver/#dfn-get-the-prompt-handler
|
||||
Web::WebDriver::PromptHandlerConfiguration WebDriverConnection::get_the_prompt_handler(Web::WebDriver::PromptType type) const
|
||||
{
|
||||
static Web::WebDriver::UserPromptHandler::ValueType empty_user_prompt_handler;
|
||||
static NeverDestroyed<Web::WebDriver::UserPromptHandler::ValueType> empty_user_prompt_handler;
|
||||
auto const& user_prompt_handler = Web::WebDriver::user_prompt_handler();
|
||||
|
||||
// 1. If the user prompt handler is null, let handlers be an empty map. Otherwise let handlers be user prompt handler.
|
||||
auto const& handlers = user_prompt_handler.has_value() ? *user_prompt_handler : empty_user_prompt_handler;
|
||||
auto const& handlers = user_prompt_handler.has_value() ? *user_prompt_handler : *empty_user_prompt_handler;
|
||||
|
||||
// 2. If handlers contains type return handlers[type].
|
||||
if (auto handler = handlers.get(type); handler.has_value())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/NeverDestroyed.h>
|
||||
#include <LibWeb/DOM/CustomEvent.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
|
|
@ -17,9 +18,23 @@
|
|||
|
||||
namespace WebContent {
|
||||
|
||||
static auto LADYBIRD_PROPERTY = JS::PropertyKey { "ladybird"_utf16_fly_string };
|
||||
static auto WEB_UI_LOADED_EVENT = "WebUILoaded"_fly_string;
|
||||
static auto WEB_UI_MESSAGE_EVENT = "WebUIMessage"_fly_string;
|
||||
static JS::PropertyKey const& ladybird_property()
|
||||
{
|
||||
static NeverDestroyed<JS::PropertyKey> property { "ladybird"_utf16_fly_string };
|
||||
return *property;
|
||||
}
|
||||
|
||||
static FlyString const& web_ui_loaded_event()
|
||||
{
|
||||
static NeverDestroyed<FlyString> event { "WebUILoaded"_fly_string };
|
||||
return *event;
|
||||
}
|
||||
|
||||
static FlyString const& web_ui_message_event()
|
||||
{
|
||||
static NeverDestroyed<FlyString> event { "WebUIMessage"_fly_string };
|
||||
return *event;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<WebUIConnection>> WebUIConnection::connect(IPC::TransportHandle handle, Web::DOM::Document& document)
|
||||
{
|
||||
|
|
@ -32,10 +47,10 @@ WebUIConnection::WebUIConnection(NonnullOwnPtr<IPC::Transport> transport, Web::D
|
|||
, m_document(document)
|
||||
{
|
||||
auto& realm = m_document->realm();
|
||||
m_document->window()->define_direct_property(LADYBIRD_PROPERTY, realm.create<Web::Internals::WebUI>(realm), JS::default_attributes);
|
||||
m_document->window()->define_direct_property(ladybird_property(), realm.create<Web::Internals::WebUI>(realm), JS::default_attributes);
|
||||
|
||||
Web::HTML::queue_a_task(Web::HTML::Task::Source::Unspecified, nullptr, m_document, GC::create_function(realm.heap(), [&document = *m_document]() {
|
||||
document.dispatch_event(Web::DOM::Event::create(document.realm(), WEB_UI_LOADED_EVENT));
|
||||
document.dispatch_event(Web::DOM::Event::create(document.realm(), web_ui_loaded_event()));
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +59,7 @@ WebUIConnection::~WebUIConnection()
|
|||
if (!m_document->window())
|
||||
return;
|
||||
|
||||
(void)m_document->window()->internal_delete(LADYBIRD_PROPERTY);
|
||||
(void)m_document->window()->internal_delete(ladybird_property());
|
||||
}
|
||||
|
||||
void WebUIConnection::visit_edges(JS::Cell::Visitor& visitor)
|
||||
|
|
@ -73,7 +88,7 @@ void WebUIConnection::send_message(String name, JsonValue data)
|
|||
Web::Bindings::CustomEventInit event_init {};
|
||||
event_init.detail = serialized_detail.value();
|
||||
|
||||
m_document->dispatch_event(Web::DOM::CustomEvent::create(realm, WEB_UI_MESSAGE_EVENT, event_init));
|
||||
m_document->dispatch_event(Web::DOM::CustomEvent::create(realm, web_ui_message_event(), event_init));
|
||||
}
|
||||
|
||||
void WebUIConnection::received_message_from_web_ui(String const& name, JS::Value data)
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ static void crash_signal_handler(int signo)
|
|||
}
|
||||
warnln("\n\033[31;1mCRASH\033[0m: Received signal {} ({})", name, signo);
|
||||
dump_backtrace(2, 100);
|
||||
exit(128 + signo);
|
||||
Core::Process::terminate_immediately(128 + signo);
|
||||
}
|
||||
|
||||
static void install_crash_signal_handlers()
|
||||
|
|
|
|||
Loading…
Reference in a new issue