LibWebView: Force-exit unresponsive child processes
Let ProcessManager own hard process termination. Callers can now schedule a forced exit after graceful shutdown is requested. The request is canceled automatically when the process monitor observes exit.
This commit is contained in:
parent
297a727970
commit
a52ff3dfd8
2 changed files with 43 additions and 0 deletions
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <LibWebView/ProcessManager.h>
|
||||
#include <signal.h>
|
||||
|
||||
namespace WebView {
|
||||
|
||||
|
|
@ -109,12 +110,48 @@ void ProcessManager::set_process_mach_port(pid_t pid, Core::MachPort&& port)
|
|||
Optional<Process> 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();
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Types.h>
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/Platform/ProcessStatistics.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibWebView/Forward.h>
|
||||
#include <LibWebView/Process.h>
|
||||
#include <LibWebView/ProcessMonitor.h>
|
||||
|
|
@ -31,6 +34,8 @@ public:
|
|||
void for_each_process(Function<void(Process&)>);
|
||||
Optional<Process> remove_process(pid_t);
|
||||
Optional<Process&> 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<pid_t, Process> m_processes;
|
||||
HashMap<pid_t, RefPtr<Core::Timer>> m_forced_exit_timers;
|
||||
ProcessMonitor m_process_monitor;
|
||||
Core::EventLoop* m_creation_event_loop { &Core::EventLoop::current() };
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue