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 <cstdlib>
12#include <cstring>
13#include <sys/wait.h>
14#include <csignal>
15#include <string>
16#include <optional>
17#include <utility>
18#include <memory>
19#include <thread>
20#include <vector>
21
22#include "../../macro.hpp"
24
25namespace ns_subprocess
26{
27
28// Forward declaration
29class Subprocess;
30
53class Child
54{
55 private:
56 pid_t m_pid;
57 std::string m_description;
58 std::vector<std::jthread> m_pipe_threads;
59
60 friend class Subprocess;
61
68 Child(pid_t pid, std::string description, std::vector<std::jthread> threads)
69 : m_pid(pid)
70 , m_description(std::move(description))
71 , m_pipe_threads(std::move(threads))
72 {}
73
82 static std::unique_ptr<Child> create(pid_t pid, std::string const& description, std::vector<std::jthread> threads = {})
83 {
84 return std::unique_ptr<Child>(new Child(pid, description, std::move(threads)));
85 }
86
87 public:
102 {
103 if (m_pid > 0)
104 {
105 std::ignore = wait();
106 }
107 }
108
109 // Delete copy and move operations - Child is non-copyable and non-moveable
110 Child(Child const&) = delete;
111 Child& operator=(Child const&) = delete;
112 Child(Child&&) = delete;
113 Child& operator=(Child&&) = delete;
114
149 [[nodiscard]] Value<int> wait()
150 {
151 // Check if pid is valid
152 return_if(m_pid <= 0, Error("E::Invalid pid to wait for in {}", m_description));
153
154 // Wait for current process
155 int status;
156 pid_t result = waitpid(m_pid, &status, 0);
157 if (result < 0)
158 {
159 if (errno == ECHILD)
160 {
161 return Error("D::Skipping wait on daemon process {}", m_pid);
162 }
163 return Error("E::waitpid failed on {}: {}", m_description, strerror(errno));
164 }
165
166 // Clear jthreads, auto-join
167 m_pipe_threads.clear();
168
169 // Mark pid as invalid to prevent double-wait
170 m_pid = -1;
171
172 return WIFEXITED(status)? Value<int>(WEXITSTATUS(status))
173 : WIFSIGNALED(status)? Error("E::The process {} was terminated by a signal", m_description)
174 : WIFSTOPPED(status)? Error("E::The process {} was stopped by a signal", m_description)
175 : Error("E::The process {} exited abnormally", m_description);
176 }
177
202 [[nodiscard]] std::optional<pid_t> get_pid() const
203 {
204 return (m_pid > 0) ? std::optional<pid_t>(m_pid) : std::nullopt;
205 }
206
228 void kill(int signal)
229 {
230 if (m_pid > 0)
231 {
232 ::kill(m_pid, signal);
233 }
234 }
235};
236
237} // namespace ns_subprocess
Handle to a spawned child process.
Definition child.hpp:54
Value< int > wait()
Waits for the child process to finish and returns exit code.
Definition child.hpp:149
std::optional< pid_t > get_pid() const
Gets the PID of the child process.
Definition child.hpp:202
void kill(int signal)
Sends a signal to the child process.
Definition child.hpp:228
~Child()
Destructor automatically waits for the child process.
Definition child.hpp:101
Enhanced error handling framework built on std::expected.
Simplified macros for common control flow patterns with optional logging.
Child process management and execution.
Enhanced expected type with integrated logging capabilities.
Definition expected.hpp:44