FlatImage
A configurable Linux containerization system
Loading...
Searching...
No Matches
child.hpp
Go to the documentation of this file.
1
8
9#pragma once
10
11#include <chrono>
12#include <fcntl.h>
13#include <string>
14#include <sys/prctl.h>
15#include <sys/wait.h>
16#include <unistd.h>
17
18#include "../std/expected.hpp"
19#include "../lib/linux.hpp"
20#include "../lib/env.hpp"
21#include "../lib/subprocess.hpp"
24#include "config.hpp"
25
26namespace fs = std::filesystem;
27
37namespace ns_portal::ns_child
38{
39
42
43
53[[nodiscard]] inline Value<void> write_fifo(int const value, fs::path const& path_fifo)
54{
55 // Write to fifo
56 ssize_t bytes_written = ns_linux::open_write_with_timeout(path_fifo
57 , std::chrono::seconds(SECONDS_TIMEOUT)
58 , std::span<pid_t const>(&value, 1)
59 );
60 // Check success with number of written bytes
61 return_if(bytes_written != sizeof(value), Error("E::Failed to write pid: {}", strerror(errno)));
62 return {};
63}
64
79[[nodiscard]] inline Value<void> spawn(std::vector<std::string> const& vec_argv
81{
84 // Split cmd / args
85 fs::path command = ({
86 auto program = Try(vec_argv.at(0));
87 auto path_bin_program = ns_env::search_path(program);
88 if(not path_bin_program)
89 {
90 write_fifo(-1, message.get_pid()).discard("C::Failed to write pid to fifo");
91 write_fifo(1, message.get_exit()).discard("C::Failed to write exit code to fifo");
92 return Error("E::Could not find program '{}'", program);
93 }
94 path_bin_program.value();
95 });
96 std::vector<std::string> args(vec_argv.begin()+1, vec_argv.end());
97 // Spawn child with a callback to open and redirect FIFOs
98 auto child = ns_subprocess::Subprocess(command)
99 .with_args(args)
100 .with_env(message.get_environment())
101 .with_die_on_pid(getpid())
102 .with_callback_child([&message]([[maybe_unused]] ns_subprocess::ArgsCallbackChild args) {
103 // Open stdin FIFO for reading and redirect to stdin (FD 0)
104 int fd_stdin = ns_linux::open_with_timeout(message.get_stdin()
105 , std::chrono::seconds(SECONDS_TIMEOUT)
106 , O_RDONLY
107 );
108 if (fd_stdin < 0 or dup2(fd_stdin, STDIN_FILENO) < 0) {
109 logger("E::Failed to open/redirect stdin FIFO: {}", strerror(errno));
110 _exit(1);
111 }
112 if (fd_stdin != STDIN_FILENO) close(fd_stdin);
113
114 // Open stdout FIFO for writing and redirect to stdout (FD 1)
115 int fd_stdout = ns_linux::open_with_timeout(message.get_stdout()
116 , std::chrono::seconds(SECONDS_TIMEOUT)
117 , O_WRONLY
118 );
119 if (fd_stdout < 0 or dup2(fd_stdout, STDOUT_FILENO) < 0) {
120 logger("E::Failed to open/redirect stdout FIFO: {}", strerror(errno));
121 _exit(1);
122 }
123 if (fd_stdout != STDOUT_FILENO) close(fd_stdout);
124
125 // Open stderr FIFO for writing and redirect to stderr (FD 2)
126 int fd_stderr = ns_linux::open_with_timeout(message.get_stderr()
127 , std::chrono::seconds(SECONDS_TIMEOUT)
128 , O_WRONLY
129 );
130 if (fd_stderr < 0 or dup2(fd_stderr, STDERR_FILENO) < 0) {
131 logger("E::Failed to open/redirect stderr FIFO: {}", strerror(errno));
132 _exit(1);
133 }
134 if (fd_stderr != STDERR_FILENO) close(fd_stderr);
135 })
136 .spawn();
137
138 // Write pid to fifo
139 pid_t pid_child = child->get_pid().value_or(-1);
140 write_fifo(pid_child, message.get_pid()).discard("C::Failed to write pid to fifo");
141 // Wait for child to finish
142 int code = Pop(child->wait(), "E::Child exited abnormally");
143 logger("D::Exit code: {}", code);
144 // Send exit code of child through a fifo
145 write_fifo(code, message.get_exit()).discard("C::Failed to write exit code to fifo");
146 return {};
147}
148
159[[nodiscard]] inline Value<void> spawn(ns_daemon::ns_log::Logs logs, ns_message::Message const& message)
160{
161 // Setup child logging
162 fs::path path_file_log = ns_fs::placeholders_replace(logs.get_path_file_child(), getpid());
163 Try(fs::create_directories(path_file_log.parent_path()));
164 ns_log::set_sink_file(ns_fs::placeholders_replace(path_file_log, getpid()));
165 // Get command from message
166 auto vec_argv = message.get_command();
167 // Ignore on empty command
168 if ( vec_argv.empty() ) { return Error("E::Empty command"); }
169 // Perform execve
170 Pop(spawn(vec_argv, message));
171 return {};
172}
173
174} // namespace ns_portal::ns_child
Subprocess & with_die_on_pid(pid_t pid)
Configures the child process to die when the specified PID dies.
Subprocess & with_callback_child(F &&f)
Sets a callback to run in the child process after fork() but before execve()
Subprocess & with_env(Args &&... args)
Includes environment variables with the format 'NAME=VALUE' in the environment.
Subprocess & with_args(Args &&... args)
Arguments forwarded as the process' arguments.
Defines a class that manages FlatImage's portal configuration.
Enhanced error handling framework built on std::expected.
A library for manipulating environment variables.
A library with helpers for linux operations.
#define logger(fmt,...)
Compile-time log level dispatch macro with automatic location capture.
Definition log.hpp:682
Defines a class that manages portal daemon message serialization/deserialization.
Portal daemon configuration and management.
Portal IPC message serialization and deserialization.
Value< fs::path > search_path(std::string const &query)
Search the directories in the PATH variable for the given input file name.
Definition env.hpp:150
fs::path placeholders_replace(fs::path const &path, Args &&... args)
Replace placeholders in a path by traversing components.
int open_with_timeout(fs::path const &path_file_src, std::chrono::milliseconds timeout, int oflag)
Opens a given file with a timeout.
Definition linux.hpp:143
ssize_t open_write_with_timeout(fs::path const &path_file_src, std::chrono::milliseconds const &timeout, std::span< Data > buf)
Opens and writes to the given input file.
Definition linux.hpp:226
void set_sink_file(fs::path const &path_file_sink)
Sets the sink file of the logger.
Definition log.hpp:359
Child process spawning and I/O management for portal IPC.
Value< void > spawn(std::vector< std::string > const &vec_argv, ns_db::ns_portal::ns_message::Message const &message)
Forks a child process and waits for it to complete.
Definition child.hpp:79
Value< void > write_fifo(int const value, fs::path const &path_fifo)
Writes a value to a fifo given a file path.
Definition child.hpp:53
Constants for portal configuration.
Enhanced expected type with integrated logging capabilities.
Definition expected.hpp:44
Arguments passed to child callback.
Arguments passed to parent callback.
A library to spawn sub-processes in linux.