diff --git a/Libraries/LibWebView/ProcessManager.cpp b/Libraries/LibWebView/ProcessManager.cpp index b3a6efa09e..28291e4681 100644 --- a/Libraries/LibWebView/ProcessManager.cpp +++ b/Libraries/LibWebView/ProcessManager.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace WebView { @@ -109,12 +110,48 @@ void ProcessManager::set_process_mach_port(pid_t pid, Core::MachPort&& port) Optional ProcessManager::remove_process(pid_t pid) { verify_event_loop(); + cancel_forced_exit(pid); m_statistics.processes.remove_first_matching([&](auto const& info) { return (info->pid == pid); }); return m_processes.take(pid); } +void ProcessManager::cancel_forced_exit(pid_t pid) +{ + verify_event_loop(); + if (auto timer = m_forced_exit_timers.take(pid); timer.has_value()) + (*timer)->stop(); +} + +void ProcessManager::force_exit_after_timeout(pid_t pid, int timeout_ms) +{ + verify_event_loop(); + if (!m_processes.contains(pid)) + return; + if (m_forced_exit_timers.contains(pid)) + return; + + auto timer = Core::Timer::create_single_shot(timeout_ms, [this, pid] { + m_forced_exit_timers.remove(pid); + auto process = m_processes.get(pid); + if (!process.has_value()) + return; + +#if defined(AK_OS_WINDOWS) + constexpr auto signal = SIGTERM; +#else + constexpr auto signal = SIGKILL; +#endif + dbgln("Force-killing unresponsive {} process {}", process_name_from_type(process->type()), pid); + auto result = Core::System::kill(pid, signal); + if (result.is_error()) + dbgln("Failed to force-kill process {}: {}", pid, result.error()); + }); + timer->start(); + m_forced_exit_timers.set(pid, move(timer)); +} + void ProcessManager::update_all_process_statistics() { verify_event_loop(); diff --git a/Libraries/LibWebView/ProcessManager.h b/Libraries/LibWebView/ProcessManager.h index 052fa3ee71..cc9e2a30db 100644 --- a/Libraries/LibWebView/ProcessManager.h +++ b/Libraries/LibWebView/ProcessManager.h @@ -7,10 +7,13 @@ #pragma once #include +#include #include +#include #include #include #include +#include #include #include #include @@ -31,6 +34,8 @@ public: void for_each_process(Function); Optional remove_process(pid_t); Optional find_process(pid_t); + void cancel_forced_exit(pid_t); + void force_exit_after_timeout(pid_t, int timeout_ms); #if defined(AK_OS_MACH) void set_process_mach_port(pid_t, Core::MachPort&&); @@ -47,6 +52,7 @@ private: Core::Platform::ProcessStatistics m_statistics; HashMap m_processes; + HashMap> m_forced_exit_timers; ProcessMonitor m_process_monitor; Core::EventLoop* m_creation_event_loop { &Core::EventLoop::current() }; };