LibCore: Keep main event loops alive
Add an explicit initializer for process-lifetime event loops and use it for browser, helper service, and utility main loops. This preserves weak event loop references for cross-thread users while making main thread loop lifetime independent of normal program teardown.
This commit is contained in:
parent
02b205361d
commit
83b293e4f2
21 changed files with 34 additions and 27 deletions
|
|
@ -42,6 +42,11 @@ EventLoop::~EventLoop()
|
|||
current_event_loop() = nullptr;
|
||||
}
|
||||
|
||||
EventLoop& EventLoop::initialize_for_current_thread()
|
||||
{
|
||||
return *new EventLoop;
|
||||
}
|
||||
|
||||
bool EventLoop::is_running()
|
||||
{
|
||||
return current_event_loop() != nullptr;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ class CORE_API EventLoop {
|
|||
AK_MAKE_NONMOVABLE(EventLoop);
|
||||
AK_MAKE_NONCOPYABLE(EventLoop);
|
||||
|
||||
private:
|
||||
public:
|
||||
enum class WaitMode {
|
||||
WaitForEvents,
|
||||
|
|
@ -54,6 +53,9 @@ public:
|
|||
EventLoop();
|
||||
~EventLoop();
|
||||
|
||||
// Create an event loop for the current thread and keep it alive for the rest of the program.
|
||||
static EventLoop& initialize_for_current_thread();
|
||||
|
||||
// Pump the event loop until its exit is requested.
|
||||
int exec();
|
||||
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ ErrorOr<void> Application::initialize(Main::Arguments const& arguments)
|
|||
|
||||
initialize_actions();
|
||||
|
||||
m_event_loop = create_platform_event_loop();
|
||||
m_event_loop = &create_platform_event_loop();
|
||||
TRY(launch_services());
|
||||
|
||||
return {};
|
||||
|
|
@ -1036,9 +1036,9 @@ ErrorOr<int> Application::execute()
|
|||
return m_event_loop->exec();
|
||||
}
|
||||
|
||||
NonnullOwnPtr<Core::EventLoop> Application::create_platform_event_loop()
|
||||
Core::EventLoop& Application::create_platform_event_loop()
|
||||
{
|
||||
return make<Core::EventLoop>();
|
||||
return Core::EventLoop::initialize_for_current_thread();
|
||||
}
|
||||
|
||||
void Application::add_child_process(WebView::Process&& process)
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ protected:
|
|||
|
||||
virtual void create_platform_arguments(Core::ArgsParser&) { }
|
||||
virtual void create_platform_options(BrowserOptions&, RequestServerOptions&, WebContentOptions&) { }
|
||||
virtual NonnullOwnPtr<Core::EventLoop> create_platform_event_loop();
|
||||
virtual Core::EventLoop& create_platform_event_loop();
|
||||
|
||||
virtual Optional<ByteString> ask_user_for_download_path([[maybe_unused]] StringView file) const { return {}; }
|
||||
|
||||
|
|
@ -352,7 +352,7 @@ private:
|
|||
|
||||
OwnPtr<Core::TimeZoneWatcher> m_time_zone_watcher;
|
||||
|
||||
OwnPtr<Core::EventLoop> m_event_loop;
|
||||
Core::EventLoop* m_event_loop { nullptr };
|
||||
OwnPtr<ProcessManager> m_process_manager;
|
||||
|
||||
RefPtr<Action> m_reload_action;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
Gfx::SkiaBackendContext::initialize_gpu_backend();
|
||||
auto skia_backend_context = Gfx::SkiaBackendContext::the_main_thread_context();
|
||||
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
auto client = TRY(IPC::take_over_accepted_client_from_system_server<Compositor::ConnectionFromClient>(
|
||||
mach_server_name, move(skia_backend_context), !disable_async_scrolling));
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
if (wait_for_debugger)
|
||||
Core::Process::wait_for_debugger_and_break();
|
||||
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
|
||||
auto client = TRY(IPC::take_over_accepted_client_from_system_server<ImageDecoder::ConnectionFromClient>(mach_server_name));
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
MUST(Core::System::signal(SIGPIPE, SIG_IGN));
|
||||
#endif
|
||||
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
// FIXME: Have another way to signal the event loop to gracefully quit on windows.
|
||||
#ifndef AK_OS_WINDOWS
|
||||
Core::EventLoop::register_signal(SIGINT, handle_signal);
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
return -1;
|
||||
}
|
||||
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
|
||||
WebView::platform_init();
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
auto webdriver_socket_path = ByteString::formatted("{}/webdriver", TRY(Core::StandardPaths::runtime_directory()));
|
||||
TRY(Core::Directory::create(webdriver_socket_path, Core::Directory::CreateDirectories::Yes));
|
||||
|
||||
Core::EventLoop loop;
|
||||
auto& loop = Core::EventLoop::initialize_for_current_thread();
|
||||
auto server = TRY(Core::TCPServer::try_create());
|
||||
|
||||
HashTable<NonnullRefPtr<WebDriver::Client>> clients;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
|
||||
auto worker_type = TRY(agent_type_from_string(worker_type_string));
|
||||
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
|
||||
WebView::platform_init();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
ErrorOr<int> service_main(int ipc_socket)
|
||||
{
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
|
||||
auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket));
|
||||
auto client = TRY(ImageDecoder::ConnectionFromClient::try_create(make<IPC::Transport>(move(socket))));
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ ErrorOr<int> service_main(int ipc_socket)
|
|||
|
||||
RequestServer::g_default_certificate_path = ByteString::formatted("{}/cacert.pem", WebView::s_ladybird_resource_root);
|
||||
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
|
||||
auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket));
|
||||
auto client = TRY(RequestServer::ConnectionFromClient::try_create(make<IPC::Transport>(move(socket))));
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ static ErrorOr<void> load_autoplay_allowlist();
|
|||
|
||||
ErrorOr<int> service_main(int ipc_socket)
|
||||
{
|
||||
Core::EventLoop event_loop;
|
||||
auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
|
||||
Web::Platform::EventLoopPlugin::install(*new Web::Platform::EventLoopPlugin);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class Application final : public WebView::Application {
|
|||
private:
|
||||
explicit Application();
|
||||
|
||||
virtual NonnullOwnPtr<Core::EventLoop> create_platform_event_loop() override;
|
||||
virtual Core::EventLoop& create_platform_event_loop() override;
|
||||
|
||||
virtual Optional<WebView::ViewImplementation&> active_web_view() const override;
|
||||
virtual Optional<WebView::ViewImplementation&> open_blank_new_tab(Web::HTML::ActivateTab) const override;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Ladybird {
|
|||
|
||||
Application::Application() = default;
|
||||
|
||||
NonnullOwnPtr<Core::EventLoop> Application::create_platform_event_loop()
|
||||
Core::EventLoop& Application::create_platform_event_loop()
|
||||
{
|
||||
if (!browser_options().headless_mode.has_value()) {
|
||||
Core::EventLoopManager::install(*new EventLoopManagerMacOS);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Application::~Application()
|
|||
g_clear_object(&m_adw_application);
|
||||
}
|
||||
|
||||
NonnullOwnPtr<Core::EventLoop> Application::create_platform_event_loop()
|
||||
Core::EventLoop& Application::create_platform_event_loop()
|
||||
{
|
||||
if (!browser_options().headless_mode.has_value()) {
|
||||
Core::EventLoopManager::install(*new EventLoopManagerGtk);
|
||||
|
|
@ -42,10 +42,10 @@ NonnullOwnPtr<Core::EventLoop> Application::create_platform_event_loop()
|
|||
setup_dbus_handlers();
|
||||
}
|
||||
|
||||
auto event_loop = WebView::Application::create_platform_event_loop();
|
||||
auto& event_loop = WebView::Application::create_platform_event_loop();
|
||||
|
||||
if (!browser_options().headless_mode.has_value())
|
||||
static_cast<EventLoopImplementationGtk&>(event_loop->impl()).set_main_loop();
|
||||
static_cast<EventLoopImplementationGtk&>(event_loop.impl()).set_main_loop();
|
||||
|
||||
return event_loop;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public:
|
|||
private:
|
||||
explicit Application();
|
||||
|
||||
virtual NonnullOwnPtr<Core::EventLoop> create_platform_event_loop() override;
|
||||
virtual Core::EventLoop& create_platform_event_loop() override;
|
||||
|
||||
virtual Optional<WebView::ViewImplementation&> active_web_view() const override;
|
||||
virtual Optional<WebView::ViewImplementation&> open_blank_new_tab(Web::HTML::ActivateTab) const override;
|
||||
|
|
|
|||
|
|
@ -124,17 +124,17 @@ void Application::create_platform_options(WebView::BrowserOptions&, WebView::Req
|
|||
web_content_options.config_path = Settings::the()->directory();
|
||||
}
|
||||
|
||||
NonnullOwnPtr<Core::EventLoop> Application::create_platform_event_loop()
|
||||
Core::EventLoop& Application::create_platform_event_loop()
|
||||
{
|
||||
if (!browser_options().headless_mode.has_value()) {
|
||||
Core::EventLoopManager::install(*new EventLoopManagerQt);
|
||||
m_application = make<LadybirdQApplication>(arguments());
|
||||
}
|
||||
|
||||
auto event_loop = WebView::Application::create_platform_event_loop();
|
||||
auto& event_loop = WebView::Application::create_platform_event_loop();
|
||||
|
||||
if (!browser_options().headless_mode.has_value())
|
||||
static_cast<EventLoopImplementationQt&>(event_loop->impl()).set_main_loop();
|
||||
static_cast<EventLoopImplementationQt&>(event_loop.impl()).set_main_loop();
|
||||
|
||||
return event_loop;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ private:
|
|||
explicit Application();
|
||||
|
||||
virtual void create_platform_options(WebView::BrowserOptions&, WebView::RequestServerOptions&, WebView::WebContentOptions&) override;
|
||||
virtual NonnullOwnPtr<Core::EventLoop> create_platform_event_loop() override;
|
||||
virtual Core::EventLoop& create_platform_event_loop() override;
|
||||
|
||||
virtual Optional<WebView::ViewImplementation&> active_web_view() const override;
|
||||
virtual Optional<WebView::ViewImplementation&> open_blank_new_tab(Web::HTML::ActivateTab) const override;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
return 1;
|
||||
}
|
||||
|
||||
Core::EventLoop loop;
|
||||
auto& loop = Core::EventLoop::initialize_for_current_thread();
|
||||
|
||||
DNS::Resolver resolver {
|
||||
[&] -> ErrorOr<DNS::Resolver::SocketResult> {
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
|
||||
StringView input { input_data };
|
||||
|
||||
[[maybe_unused]] Core::EventLoop event_loop;
|
||||
[[maybe_unused]] auto& event_loop = Core::EventLoop::initialize_for_current_thread();
|
||||
Web::Platform::EventLoopPlugin::install(*new Web::Platform::EventLoopPlugin);
|
||||
Web::Platform::FontPlugin::install(*new Web::Platform::FontPlugin(false));
|
||||
Web::Bindings::initialize_main_thread_vm(Web::Bindings::AgentType::SimilarOriginWindow);
|
||||
|
|
|
|||
Loading…
Reference in a new issue