mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-02 06:04:15 +00:00
LibCore: Support launching a process with an IPC connection
Much of the code here is adapted from Ladybird. But rather than doing a manual fork, we use Core::Process to spawn the underlying process.
This commit is contained in:
parent
dc52404aec
commit
9986350e97
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
|
||||
* Copyright (c) 2023-2024, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include <LibCore/Environment.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibCore/Process.h>
|
||||
#include <LibCore/Socket.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <errno.h>
|
||||
#include <spawn.h>
|
||||
|
@ -351,4 +353,27 @@ 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<Vector<ProcessSpawnOptions::FileActionType>&>(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) };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2022, MacDue <macdue@dueutil.tech>
|
||||
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -33,11 +34,14 @@ struct CloseFile {
|
|||
}
|
||||
|
||||
struct ProcessSpawnOptions {
|
||||
ByteString executable;
|
||||
StringView name {};
|
||||
ByteString executable {};
|
||||
bool search_for_executable_in_path { false };
|
||||
Vector<ByteString> const& arguments {};
|
||||
Optional<ByteString> working_directory {};
|
||||
Vector<Variant<FileAction::OpenFile, FileAction::CloseFile>> const& file_actions {};
|
||||
|
||||
using FileActionType = Variant<FileAction::OpenFile, FileAction::CloseFile>;
|
||||
Vector<FileActionType> const& file_actions {};
|
||||
};
|
||||
|
||||
class Process {
|
||||
|
@ -99,4 +103,33 @@ private:
|
|||
bool m_should_disown;
|
||||
};
|
||||
|
||||
class IPCProcess {
|
||||
public:
|
||||
template<typename ClientType>
|
||||
struct ProcessAndIPCClient {
|
||||
Process process;
|
||||
NonnullRefPtr<ClientType> client;
|
||||
};
|
||||
|
||||
template<typename ClientType, typename... ClientArguments>
|
||||
static ErrorOr<ProcessAndIPCClient<ClientType>> spawn(ProcessSpawnOptions const& options, ClientArguments&&... client_arguments)
|
||||
{
|
||||
auto [process, socket] = TRY(spawn_and_connect_to_process(options));
|
||||
auto client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ClientType { move(socket), forward<ClientArguments>(client_arguments)... }));
|
||||
|
||||
return ProcessAndIPCClient<ClientType> { move(process), move(client) };
|
||||
}
|
||||
|
||||
pid_t pid() const { return m_process.pid(); }
|
||||
|
||||
private:
|
||||
struct ProcessAndIPCSocket {
|
||||
Process process;
|
||||
NonnullOwnPtr<Core::LocalSocket> m_ipc_socket;
|
||||
};
|
||||
static ErrorOr<ProcessAndIPCSocket> spawn_and_connect_to_process(ProcessSpawnOptions const& options);
|
||||
|
||||
Process m_process;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue