WebContent: Exit cleanly when browser IPC disconnects
Exit WebContent immediately when either browser-side IPC peer disconnects. Plumb Unix process exit status through LibWebView so the browser process can tell clean owner-driven shutdown apart from renderer crashes. This keeps nonzero exits and signal deaths reported as crashes, while letting status 0 exits disappear without making test-web report the page as crashed.
This commit is contained in:
parent
9a0bcd930b
commit
a031d00695
9 changed files with 29 additions and 18 deletions
|
|
@ -35,6 +35,10 @@
|
|||
# include <LibIPC/TransportBootstrapMach.h>
|
||||
#endif
|
||||
|
||||
#if !defined(AK_OS_WINDOWS)
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
namespace WebView {
|
||||
|
||||
Application* Application::s_the = nullptr;
|
||||
|
|
@ -472,8 +476,8 @@ ErrorOr<void> Application::launch_services()
|
|||
m_bookmark_store_observer = make<ApplicationBookmarkStoreObserver>();
|
||||
|
||||
m_process_manager = make<ProcessManager>();
|
||||
m_process_manager->on_process_exited = [this](Process&& process) {
|
||||
process_did_exit(move(process));
|
||||
m_process_manager->on_process_exited = [this](Process&& process, Optional<int> exit_status) {
|
||||
process_did_exit(move(process), exit_status);
|
||||
};
|
||||
|
||||
if (m_browser_options.disable_sql_database == DisableSQLDatabase::No) {
|
||||
|
|
@ -727,7 +731,7 @@ Optional<Process&> Application::find_process(pid_t pid)
|
|||
return m_process_manager->find_process(pid);
|
||||
}
|
||||
|
||||
void Application::process_did_exit(Process&& process)
|
||||
void Application::process_did_exit(Process&& process, Optional<int> exit_status)
|
||||
{
|
||||
if (m_event_loop->was_exit_requested())
|
||||
return;
|
||||
|
|
@ -751,6 +755,10 @@ void Application::process_did_exit(Process&& process)
|
|||
}
|
||||
break;
|
||||
case ProcessType::WebContent:
|
||||
#if !defined(AK_OS_WINDOWS)
|
||||
if (exit_status.has_value() && WIFEXITED(*exit_status) && WEXITSTATUS(*exit_status) == 0)
|
||||
break;
|
||||
#endif
|
||||
if (auto client = process.client<WebContentClient>(); client.has_value())
|
||||
client->notify_all_views_of_crash();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ protected:
|
|||
|
||||
ErrorOr<void> initialize(Main::Arguments const&);
|
||||
|
||||
virtual void process_did_exit(Process&&);
|
||||
virtual void process_did_exit(Process&&, Optional<int> exit_status);
|
||||
|
||||
virtual void create_platform_arguments(Core::ArgsParser&) { }
|
||||
virtual void create_platform_options(BrowserOptions&, RequestServerOptions&, WebContentOptions&) { }
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ StringView process_name_from_type(ProcessType type)
|
|||
|
||||
ProcessManager::ProcessManager()
|
||||
: on_process_added([](Process&) {})
|
||||
, on_process_exited([](Process&&) {})
|
||||
, m_process_monitor(ProcessMonitor([this](pid_t pid) {
|
||||
, on_process_exited([](Process&&, Optional<int>) {})
|
||||
, m_process_monitor(ProcessMonitor([this](pid_t pid, Optional<int> exit_status) {
|
||||
if (auto process = remove_process(pid); process.has_value())
|
||||
on_process_exited(process.release_value());
|
||||
on_process_exited(process.release_value(), exit_status);
|
||||
}))
|
||||
{
|
||||
add_process(Process(WebView::ProcessType::Browser, nullptr, Core::Process::current()));
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public:
|
|||
JsonValue serialize_json();
|
||||
|
||||
Function<void(Process&)> on_process_added; // test-web
|
||||
Function<void(Process&&)> on_process_exited;
|
||||
Function<void(Process&&, Optional<int> exit_status)> on_process_exited;
|
||||
|
||||
private:
|
||||
void verify_event_loop() const;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
namespace WebView {
|
||||
|
||||
ProcessMonitor::ProcessMonitor(Function<void(pid_t)> exit_handler)
|
||||
ProcessMonitor::ProcessMonitor(Function<void(pid_t, Optional<int> exit_status)> exit_handler)
|
||||
: m_on_process_exit(move(exit_handler))
|
||||
{
|
||||
#if !defined(AK_OS_WINDOWS)
|
||||
|
|
@ -23,7 +23,7 @@ ProcessMonitor::ProcessMonitor(Function<void(pid_t)> exit_handler)
|
|||
if (m_monitored_processes.contains(pid)) {
|
||||
if (WIFEXITED(status) || WIFSIGNALED(status)) {
|
||||
m_monitored_processes.remove(pid);
|
||||
m_on_process_exit(pid);
|
||||
m_on_process_exit(pid, status);
|
||||
}
|
||||
}
|
||||
result = Core::System::waitpid(-1, WNOHANG);
|
||||
|
|
@ -51,7 +51,7 @@ void ProcessMonitor::add_process(pid_t pid)
|
|||
#if defined(AK_OS_WINDOWS)
|
||||
Core::EventLoop::register_process(pid, [this](pid_t pid) {
|
||||
m_monitored_processes.remove(pid);
|
||||
m_on_process_exit(pid);
|
||||
m_on_process_exit(pid, {});
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@ namespace WebView {
|
|||
|
||||
class ProcessMonitor {
|
||||
public:
|
||||
ProcessMonitor(Function<void(pid_t)> exit_handler);
|
||||
ProcessMonitor(Function<void(pid_t, Optional<int> exit_status)> exit_handler);
|
||||
~ProcessMonitor();
|
||||
|
||||
void add_process(pid_t pid);
|
||||
|
||||
private:
|
||||
Function<void(pid_t)> m_on_process_exit;
|
||||
Function<void(pid_t, Optional<int> exit_status)> m_on_process_exit;
|
||||
HashTable<pid_t> m_monitored_processes;
|
||||
[[maybe_unused]] int m_signal_handle { -1 };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,7 +78,10 @@ class CompositorConnectionFromClient final
|
|||
C_OBJECT(CompositorConnectionFromClient)
|
||||
|
||||
public:
|
||||
virtual void die() override { }
|
||||
virtual void die() override
|
||||
{
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit CompositorConnectionFromClient(NonnullOwnPtr<IPC::Transport> transport)
|
||||
|
|
@ -134,7 +137,7 @@ ConnectionFromClient::~ConnectionFromClient() = default;
|
|||
|
||||
void ConnectionFromClient::die()
|
||||
{
|
||||
Web::Platform::EventLoopPlugin::the().quit();
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
Messages::WebContentServer::InitTransportResponse ConnectionFromClient::init_transport([[maybe_unused]] int peer_pid)
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ TestRunCapture::TestRunCapture()
|
|||
setup_output_capture_for_helper_process(process);
|
||||
};
|
||||
m_previous_on_process_exited = move(process_manager.on_process_exited);
|
||||
process_manager.on_process_exited = [this](WebView::Process&& process) {
|
||||
process_manager.on_process_exited = [this](WebView::Process&& process, Optional<int> exit_status) {
|
||||
consume_helper_capture(process.pid());
|
||||
m_previous_on_process_exited(move(process));
|
||||
m_previous_on_process_exited(move(process), exit_status);
|
||||
};
|
||||
|
||||
process_manager.for_each_process([this](WebView::Process& process) {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ private:
|
|||
void consume_helper_capture(pid_t pid);
|
||||
void destroy_view_capture_of(TestWebView const& view);
|
||||
|
||||
Function<void(WebView::Process&&)> m_previous_on_process_exited;
|
||||
Function<void(WebView::Process&&, Optional<int> exit_status)> m_previous_on_process_exited;
|
||||
HashMap<TestWebView const*, NonnullOwnPtr<ViewOutputCapture>> m_test_output_captures;
|
||||
HashMap<pid_t, NonnullOwnPtr<HelperOutputCapture>> m_helper_output_captures;
|
||||
CaptureFile m_helper_output;
|
||||
|
|
|
|||
Loading…
Reference in a new issue