mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-06 09:36:08 +00:00
Ladybird+LibWebView: Add ProcessManager to track live processes
This model will be used to add a Processes tab to the inspector.
This commit is contained in:
parent
e66a4668f9
commit
096feaaeb8
Notes:
sideshowbarker
2024-07-16 20:08:14 +09:00
Author: https://github.com/ADKaster
Commit: 096feaaeb8
Pull-request: https://github.com/SerenityOS/serenity/pull/23745
Reviewed-by: https://github.com/alimpfard
Reviewed-by: https://github.com/trflynn89
9 changed files with 193 additions and 2 deletions
|
@ -13,6 +13,7 @@
|
||||||
#include <LibMain/Main.h>
|
#include <LibMain/Main.h>
|
||||||
#include <LibWebView/CookieJar.h>
|
#include <LibWebView/CookieJar.h>
|
||||||
#include <LibWebView/Database.h>
|
#include <LibWebView/Database.h>
|
||||||
|
#include <LibWebView/ProcessManager.h>
|
||||||
#include <LibWebView/URL.h>
|
#include <LibWebView/URL.h>
|
||||||
|
|
||||||
#import <Application/Application.h>
|
#import <Application/Application.h>
|
||||||
|
@ -81,6 +82,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
.wait_for_debugger = debug_web_content ? Ladybird::WaitForDebugger::Yes : Ladybird::WaitForDebugger::No,
|
.wait_for_debugger = debug_web_content ? Ladybird::WaitForDebugger::Yes : Ladybird::WaitForDebugger::No,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WebView::ProcessManager::initialize();
|
||||||
|
|
||||||
auto* delegate = [[ApplicationDelegate alloc] init:move(initial_urls)
|
auto* delegate = [[ApplicationDelegate alloc] init:move(initial_urls)
|
||||||
newTabPageURL:move(new_tab_page_url)
|
newTabPageURL:move(new_tab_page_url)
|
||||||
withCookieJar:move(cookie_jar)
|
withCookieJar:move(cookie_jar)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "HelperProcess.h"
|
#include "HelperProcess.h"
|
||||||
#include <LibCore/Environment.h>
|
#include <LibCore/Environment.h>
|
||||||
|
#include <LibWebView/ProcessManager.h>
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
WebView::ViewImplementation& view,
|
WebView::ViewImplementation& view,
|
||||||
|
@ -24,7 +25,8 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
int ui_fd_passing_fd = fd_passing_socket_fds[0];
|
int ui_fd_passing_fd = fd_passing_socket_fds[0];
|
||||||
int wc_fd_passing_fd = fd_passing_socket_fds[1];
|
int wc_fd_passing_fd = fd_passing_socket_fds[1];
|
||||||
|
|
||||||
if (auto child_pid = TRY(Core::System::fork()); child_pid == 0) {
|
auto child_pid = TRY(Core::System::fork());
|
||||||
|
if (child_pid == 0) {
|
||||||
TRY(Core::System::close(ui_fd_passing_fd));
|
TRY(Core::System::close(ui_fd_passing_fd));
|
||||||
TRY(Core::System::close(ui_fd));
|
TRY(Core::System::close(ui_fd));
|
||||||
|
|
||||||
|
@ -94,6 +96,8 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
dbgln();
|
dbgln();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebView::ProcessManager::the().add_process(WebView::ProcessType::WebContent, child_pid);
|
||||||
|
|
||||||
return new_client;
|
return new_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +116,8 @@ ErrorOr<NonnullRefPtr<Client>> launch_generic_server_process(ReadonlySpan<ByteSt
|
||||||
int ui_fd_passing_fd = fd_passing_socket_fds[0];
|
int ui_fd_passing_fd = fd_passing_socket_fds[0];
|
||||||
int server_fd_passing_fd = fd_passing_socket_fds[1];
|
int server_fd_passing_fd = fd_passing_socket_fds[1];
|
||||||
|
|
||||||
if (auto child_pid = TRY(Core::System::fork()); child_pid == 0) {
|
auto child_pid = TRY(Core::System::fork());
|
||||||
|
if (child_pid == 0) {
|
||||||
TRY(Core::System::close(ui_fd));
|
TRY(Core::System::close(ui_fd));
|
||||||
TRY(Core::System::close(ui_fd_passing_fd));
|
TRY(Core::System::close(ui_fd_passing_fd));
|
||||||
|
|
||||||
|
@ -161,6 +166,8 @@ ErrorOr<NonnullRefPtr<Client>> launch_generic_server_process(ReadonlySpan<ByteSt
|
||||||
auto new_client = TRY(try_make_ref_counted<Client>(move(socket)));
|
auto new_client = TRY(try_make_ref_counted<Client>(move(socket)));
|
||||||
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
|
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
|
||||||
|
|
||||||
|
WebView::ProcessManager::the().add_process(WebView::process_type_from_name(server_name), child_pid);
|
||||||
|
|
||||||
return new_client;
|
return new_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <LibMain/Main.h>
|
#include <LibMain/Main.h>
|
||||||
#include <LibWebView/CookieJar.h>
|
#include <LibWebView/CookieJar.h>
|
||||||
#include <LibWebView/Database.h>
|
#include <LibWebView/Database.h>
|
||||||
|
#include <LibWebView/ProcessManager.h>
|
||||||
#include <LibWebView/URL.h>
|
#include <LibWebView/URL.h>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QFileOpenEvent>
|
#include <QFileOpenEvent>
|
||||||
|
@ -157,6 +158,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
.wait_for_debugger = debug_web_content ? Ladybird::WaitForDebugger::Yes : Ladybird::WaitForDebugger::No,
|
.wait_for_debugger = debug_web_content ? Ladybird::WaitForDebugger::Yes : Ladybird::WaitForDebugger::No,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WebView::ProcessManager::initialize();
|
||||||
|
|
||||||
Ladybird::BrowserWindow window(initial_urls, cookie_jar, web_content_options, webdriver_content_ipc_path);
|
Ladybird::BrowserWindow window(initial_urls, cookie_jar, web_content_options, webdriver_content_ipc_path);
|
||||||
window.setWindowTitle("Ladybird");
|
window.setWindowTitle("Ladybird");
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@ shared_library("LibWebView") {
|
||||||
"Database.cpp",
|
"Database.cpp",
|
||||||
"History.cpp",
|
"History.cpp",
|
||||||
"InspectorClient.cpp",
|
"InspectorClient.cpp",
|
||||||
|
"ProcessManager.cpp",
|
||||||
"RequestServerAdapter.cpp",
|
"RequestServerAdapter.cpp",
|
||||||
"SearchEngine.cpp",
|
"SearchEngine.cpp",
|
||||||
"SocketPair.cpp",
|
"SocketPair.cpp",
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <LibWebView/CookieJar.h>
|
#include <LibWebView/CookieJar.h>
|
||||||
#include <LibWebView/Database.h>
|
#include <LibWebView/Database.h>
|
||||||
#include <LibWebView/OutOfProcessWebView.h>
|
#include <LibWebView/OutOfProcessWebView.h>
|
||||||
|
#include <LibWebView/ProcessManager.h>
|
||||||
#include <LibWebView/RequestServerAdapter.h>
|
#include <LibWebView/RequestServerAdapter.h>
|
||||||
#include <LibWebView/SearchEngine.h>
|
#include <LibWebView/SearchEngine.h>
|
||||||
#include <LibWebView/URL.h>
|
#include <LibWebView/URL.h>
|
||||||
|
@ -94,6 +95,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRY(Core::System::pledge("sigaction stdio recvfd sendfd unix fattr cpath rpath wpath proc exec"));
|
||||||
|
|
||||||
|
WebView::ProcessManager::initialize();
|
||||||
|
|
||||||
TRY(Core::System::pledge("stdio recvfd sendfd unix fattr cpath rpath wpath proc exec"));
|
TRY(Core::System::pledge("stdio recvfd sendfd unix fattr cpath rpath wpath proc exec"));
|
||||||
|
|
||||||
Vector<StringView> specified_urls;
|
Vector<StringView> specified_urls;
|
||||||
|
|
|
@ -6,6 +6,7 @@ set(SOURCES
|
||||||
Database.cpp
|
Database.cpp
|
||||||
History.cpp
|
History.cpp
|
||||||
InspectorClient.cpp
|
InspectorClient.cpp
|
||||||
|
ProcessManager.cpp
|
||||||
RequestServerAdapter.cpp
|
RequestServerAdapter.cpp
|
||||||
SearchEngine.cpp
|
SearchEngine.cpp
|
||||||
SocketPair.cpp
|
SocketPair.cpp
|
||||||
|
|
|
@ -15,6 +15,7 @@ class Database;
|
||||||
class History;
|
class History;
|
||||||
class InspectorClient;
|
class InspectorClient;
|
||||||
class OutOfProcessWebView;
|
class OutOfProcessWebView;
|
||||||
|
class ProcessManager;
|
||||||
class ViewImplementation;
|
class ViewImplementation;
|
||||||
class WebContentClient;
|
class WebContentClient;
|
||||||
|
|
||||||
|
|
117
Userland/Libraries/LibWebView/ProcessManager.cpp
Normal file
117
Userland/Libraries/LibWebView/ProcessManager.cpp
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibCore/EventLoop.h>
|
||||||
|
#include <LibCore/System.h>
|
||||||
|
#include <LibWebView/ProcessManager.h>
|
||||||
|
|
||||||
|
namespace WebView {
|
||||||
|
|
||||||
|
static sig_atomic_t s_received_sigchld = 0;
|
||||||
|
|
||||||
|
ProcessType process_type_from_name(StringView name)
|
||||||
|
{
|
||||||
|
if (name == "Chrome"sv)
|
||||||
|
return ProcessType::Chrome;
|
||||||
|
if (name == "WebContent"sv)
|
||||||
|
return ProcessType::WebContent;
|
||||||
|
if (name == "WebWorker"sv)
|
||||||
|
return ProcessType::WebWorker;
|
||||||
|
if (name == "SQLServer"sv)
|
||||||
|
return ProcessType::SQLServer;
|
||||||
|
if (name == "RequestServer"sv)
|
||||||
|
return ProcessType::RequestServer;
|
||||||
|
if (name == "ImageDecoder"sv)
|
||||||
|
return ProcessType::ImageDecoder;
|
||||||
|
|
||||||
|
dbgln("Unknown process type: '{}'", name);
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView process_name_from_type(ProcessType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ProcessType::Chrome:
|
||||||
|
return "Chrome"sv;
|
||||||
|
case ProcessType::WebContent:
|
||||||
|
return "WebContent"sv;
|
||||||
|
case ProcessType::WebWorker:
|
||||||
|
return "WebWorker"sv;
|
||||||
|
case ProcessType::SQLServer:
|
||||||
|
return "SQLServer"sv;
|
||||||
|
case ProcessType::RequestServer:
|
||||||
|
return "RequestServer"sv;
|
||||||
|
case ProcessType::ImageDecoder:
|
||||||
|
return "ImageDecoder"sv;
|
||||||
|
}
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessManager::ProcessManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessManager::~ProcessManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessManager& ProcessManager::the()
|
||||||
|
{
|
||||||
|
static ProcessManager s_the;
|
||||||
|
return s_the;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessManager::initialize()
|
||||||
|
{
|
||||||
|
// FIXME: Should we change this to call EventLoop::register_signal?
|
||||||
|
// Note that only EventLoopImplementationUnix has a working register_signal
|
||||||
|
|
||||||
|
struct sigaction action { };
|
||||||
|
action.sa_flags = SA_RESTART;
|
||||||
|
action.sa_sigaction = [](int, auto*, auto) {
|
||||||
|
s_received_sigchld = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
MUST(Core::System::sigaction(SIGCHLD, &action, nullptr));
|
||||||
|
|
||||||
|
the().add_process(WebView::ProcessType::Chrome, getpid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessManager::add_process(ProcessType type, pid_t pid)
|
||||||
|
{
|
||||||
|
dbgln("ProcessManager::add_process({}, {})", process_name_from_type(type), pid);
|
||||||
|
m_processes.append({ type, pid, 0, 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessManager::remove_process(pid_t pid)
|
||||||
|
{
|
||||||
|
m_processes.remove_first_matching([&](auto& info) {
|
||||||
|
if (info.pid == pid) {
|
||||||
|
dbgln("ProcessManager: Remove process {} ({})", process_name_from_type(info.type), pid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessManager::update_all_processes()
|
||||||
|
{
|
||||||
|
if (s_received_sigchld) {
|
||||||
|
s_received_sigchld = 0;
|
||||||
|
auto result = Core::System::waitpid(-1, WNOHANG);
|
||||||
|
while (!result.is_error() && result.value().pid > 0) {
|
||||||
|
auto& [pid, status] = result.value();
|
||||||
|
if (WIFEXITED(status) || WIFSIGNALED(status)) {
|
||||||
|
remove_process(pid);
|
||||||
|
}
|
||||||
|
result = Core::System::waitpid(-1, WNOHANG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Actually gather stats in a platform-specific way
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
Userland/Libraries/LibWebView/ProcessManager.h
Normal file
53
Userland/Libraries/LibWebView/ProcessManager.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/Types.h>
|
||||||
|
#include <AK/Vector.h>
|
||||||
|
#include <LibCore/EventReceiver.h>
|
||||||
|
#include <LibWebView/Forward.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace WebView {
|
||||||
|
|
||||||
|
enum class ProcessType {
|
||||||
|
Chrome,
|
||||||
|
WebContent,
|
||||||
|
WebWorker,
|
||||||
|
SQLServer,
|
||||||
|
RequestServer,
|
||||||
|
ImageDecoder,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProcessInfo {
|
||||||
|
ProcessType type;
|
||||||
|
pid_t pid;
|
||||||
|
u64 memory_usage_kib = 0;
|
||||||
|
float cpu_percent = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
ProcessType process_type_from_name(StringView);
|
||||||
|
StringView process_name_from_type(ProcessType type);
|
||||||
|
|
||||||
|
class ProcessManager {
|
||||||
|
public:
|
||||||
|
static ProcessManager& the();
|
||||||
|
static void initialize();
|
||||||
|
|
||||||
|
void add_process(WebView::ProcessType, pid_t);
|
||||||
|
void remove_process(pid_t);
|
||||||
|
|
||||||
|
void update_all_processes();
|
||||||
|
Vector<ProcessInfo> processes() const { return m_processes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProcessManager();
|
||||||
|
~ProcessManager();
|
||||||
|
|
||||||
|
Vector<ProcessInfo> m_processes;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue