LibWebView+LibCore: Move IPCProcess into WebView::Process

Ladybird's HelperProcess.cpp was the only user of the IPCProcess class.
Moving the helper class from LibCore allows for some more interesting
LibIPC changes in the upcoming commits.
This commit is contained in:
Andrew Kaster
2024-10-22 13:27:15 -06:00
committed by Andrew Kaster
parent e537adad77
commit 9a6eccc590
6 changed files with 144 additions and 151 deletions

View File

@@ -14,9 +14,6 @@
#include <LibCore/Environment.h>
#include <LibCore/File.h>
#include <LibCore/Process.h>
#include <LibCore/Socket.h>
#include <LibCore/SocketAddress.h>
#include <LibCore/StandardPaths.h>
#include <LibCore/System.h>
#include <errno.h>
#include <signal.h>
@@ -363,101 +360,4 @@ ErrorOr<bool> Process::wait_for_termination()
return exited_with_code_0;
}
ErrorOr<IPCProcess::ProcessAndIPCSocket> IPCProcess::spawn_and_connect_to_process(ProcessSpawnOptions const& options)
{
int socket_fds[2] {};
TRY(System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
ArmedScopeGuard guard_fd_0 { [&] { MUST(System::close(socket_fds[0])); } };
ArmedScopeGuard guard_fd_1 { [&] { MUST(System::close(socket_fds[1])); } };
auto& file_actions = const_cast<ProcessSpawnOptions&>(options).file_actions;
file_actions.append(FileAction::CloseFile { socket_fds[0] });
auto takeover_string = MUST(String::formatted("{}:{}", options.name, socket_fds[1]));
TRY(Environment::set("SOCKET_TAKEOVER"sv, takeover_string, Environment::Overwrite::Yes));
auto process = TRY(Process::spawn(options));
auto ipc_socket = TRY(LocalSocket::adopt_fd(socket_fds[0]));
guard_fd_0.disarm();
TRY(ipc_socket->set_blocking(true));
return ProcessAndIPCSocket { move(process), move(ipc_socket) };
}
ErrorOr<Optional<pid_t>> IPCProcess::get_process_pid(StringView process_name, StringView pid_path)
{
if (System::stat(pid_path).is_error())
return OptionalNone {};
Optional<pid_t> pid;
{
auto pid_file = File::open(pid_path, File::OpenMode::Read);
if (pid_file.is_error()) {
warnln("Could not open {} PID file '{}': {}", process_name, pid_path, pid_file.error());
return pid_file.release_error();
}
auto contents = pid_file.value()->read_until_eof();
if (contents.is_error()) {
warnln("Could not read {} PID file '{}': {}", process_name, pid_path, contents.error());
return contents.release_error();
}
pid = StringView { contents.value() }.to_number<pid_t>();
}
if (!pid.has_value()) {
warnln("{} PID file '{}' exists, but with an invalid PID", process_name, pid_path);
TRY(System::unlink(pid_path));
return OptionalNone {};
}
if (kill(*pid, 0) < 0) {
warnln("{} PID file '{}' exists with PID {}, but process cannot be found", process_name, pid_path, *pid);
TRY(System::unlink(pid_path));
return OptionalNone {};
}
return pid;
}
// This is heavily based on how SystemServer's Service creates its socket.
ErrorOr<int> IPCProcess::create_ipc_socket(ByteString const& socket_path)
{
if (!System::stat(socket_path).is_error())
TRY(System::unlink(socket_path));
#ifdef SOCK_NONBLOCK
auto socket_fd = TRY(System::socket(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
#else
auto socket_fd = TRY(System::socket(AF_LOCAL, SOCK_STREAM, 0));
int option = 1;
TRY(System::ioctl(socket_fd, FIONBIO, &option));
TRY(System::fcntl(socket_fd, F_SETFD, FD_CLOEXEC));
#endif
#if !defined(AK_OS_BSD_GENERIC) && !defined(AK_OS_GNU_HURD)
TRY(System::fchmod(socket_fd, 0600));
#endif
auto socket_address = SocketAddress::local(socket_path);
auto socket_address_un = socket_address.to_sockaddr_un().release_value();
TRY(System::bind(socket_fd, reinterpret_cast<sockaddr*>(&socket_address_un), sizeof(socket_address_un)));
TRY(System::listen(socket_fd, 16));
return socket_fd;
}
ErrorOr<IPCProcess::ProcessPaths> IPCProcess::paths_for_process(StringView process_name)
{
auto runtime_directory = TRY(StandardPaths::runtime_directory());
auto socket_path = ByteString::formatted("{}/{}.socket", runtime_directory, process_name);
auto pid_path = ByteString::formatted("{}/{}.pid", runtime_directory, process_name);
return ProcessPaths { move(socket_path), move(pid_path) };
}
}