13 #ifndef __STOUT_OS_POSIX_FORK_HPP__
14 #define __STOUT_OS_POSIX_FORK_HPP__
23 #include <sys/types.h>
103 Exec(
const std::string& _command)
118 : function(_function),
127 : function(_function)
129 children.push_back(fork1);
135 : function(_function),
138 children.push_back(fork1);
144 : function(_function),
147 children.push_back(fork1);
157 : function(_function)
159 children.push_back(fork1);
160 children.push_back(fork2);
167 : function(_function),
170 children.push_back(fork1);
171 children.push_back(fork2);
178 : function(_function),
181 children.push_back(fork1);
182 children.push_back(fork2);
194 : function(_function)
196 children.push_back(fork1);
197 children.push_back(fork2);
198 children.push_back(fork3);
206 : function(_function),
209 children.push_back(fork1);
210 children.push_back(fork2);
211 children.push_back(fork3);
219 : function(_function),
222 children.push_back(fork1);
223 children.push_back(fork2);
224 children.push_back(fork3);
244 std::shared_ptr<Memory>
memory;
262 struct SharedMemoryDeleter
264 SharedMemoryDeleter(
int _fd) : fd(_fd) {}
268 if (munmap(process,
sizeof(Tree::Memory)) == -1) {
271 if (::
close(fd) == -1) {
272 ABORT(std::string(
"Failed to close shared memory file descriptor: ") +
283 static std::atomic_int forks(0);
287 int instance = forks.fetch_add(1);
295 return ErrnoError(
"Failed to open a shared memory object");
301 "Failed to set size of shared memory object: " + truncated.
error());
306 sizeof(Tree::Memory),
307 PROT_READ | PROT_WRITE, MAP_SHARED,
311 if (memory == MAP_FAILED) {
312 return ErrnoError(
"Failed to map shared memory object");
315 if (shm_unlink(name.c_str()) == -1) {
316 return ErrnoError(
"Failed to unlink shared memory object");
319 SharedMemoryDeleter deleter(fd);
322 tree.memory = std::shared_ptr<Tree::Memory>((Tree::Memory*)memory, deleter);
323 tree.memory->set.store(
false);
325 for (
size_t i = 0; i < children.size(); i++) {
330 tree.children.push_back(tree_.
get());
338 pid_t instantiate(
const Tree& tree)
const
340 pid_t pid = ::fork();
347 process.pid = getpid();
348 process.parent = getppid();
349 process.group = getpgid(0);
350 process.session = getsid(0);
351 process.set.store(
true);
354 memcpy(tree.memory.get(), &
process,
sizeof(Tree::Memory));
357 if (
function.isSome()) {
362 CHECK(children.size() == tree.children.size());
363 std::set<pid_t>
pids;
364 for (
size_t i = 0; i < children.size(); i++) {
365 pids.insert(children[i].instantiate(tree.children[i]));
371 const char* command = exec.get().command.c_str();
372 execlp(
"sh",
"sh",
"-c", command, (
char*)
nullptr);
374 <<
"Failed to execute '" << command <<
"': " <<
os::strerror(errno);
375 }
else if (wait.isSome()) {
376 foreach (
pid_t pid, pids) {
393 while (!tree.memory->set.load());
401 Process process = Process(
405 tree.memory->session,
409 self.isSome() ?
self.
get().command :
"",
412 std::list<ProcessTree> children;
413 for (
size_t i = 0; i < tree.children.size(); i++) {
418 children.push_back(child.
get());
421 return ProcessTree(process, children);
440 return coordinate(tree.
get());
447 std::vector<Fork> children;
452 #endif // __STOUT_OS_POSIX_FORK_HPP__
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Fork &fork2)
Definition: fork.hpp:154
std::string strerror(int errno_)
A thread-safe version of strerror.
Definition: strerror.hpp:30
Definition: errorbase.hpp:35
Definition: option.hpp:28
#define ABORT(...)
Definition: abort.hpp:40
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Fork &fork2, const Exec &_exec)
Definition: fork.hpp:163
int execlp(const char *file, T...t)
Definition: shell.hpp:186
const mode_t S_IWUSR
Definition: windows.hpp:312
pid_t session
Definition: fork.hpp:239
#define EXIT(status)
Definition: exit.hpp:31
Definition: errorbase.hpp:49
#define O_CREAT
Definition: fcntl.hpp:28
const mode_t S_IRUSR
Definition: windows.hpp:311
Fork(const Option< void(*)()> &_function, const Fork &fork1)
Definition: fork.hpp:125
Definition: result.hpp:40
Fork(const Option< void(*)()> &_function, const Exec &_exec)
Definition: fork.hpp:116
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Fork &fork2, const Fork &fork3)
Definition: fork.hpp:190
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Fork &fork2, const Fork &fork3, const Exec &_exec)
Definition: fork.hpp:201
Fork(const Exec &_exec)
Definition: fork.hpp:121
DWORD pid_t
Definition: windows.hpp:187
Try< ProcessTree > operator()() const
Definition: fork.hpp:426
Try< Nothing > close(int fd)
Definition: close.hpp:24
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Fork &fork2, const Fork &fork3, const Wait &_wait)
Definition: fork.hpp:214
Result< pid_t > waitpid(pid_t pid, int *status, int options)
Definition: os.hpp:141
static Try error(const E &e)
Definition: try.hpp:42
pid_t pid
Definition: fork.hpp:236
pid_t group
Definition: fork.hpp:238
Result< Process > process(pid_t pid)
Definition: freebsd.hpp:30
bool isError() const
Definition: try.hpp:71
std::set< pid_t > children(pid_t, const std::list< Process > &, bool)
Definition: os.hpp:215
const std::string command
Definition: fork.hpp:106
pid_t parent
Definition: fork.hpp:237
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Fork &fork2, const Wait &_wait)
Definition: fork.hpp:174
#define O_RDWR
Definition: fcntl.hpp:27
std::string stringify(int flags)
Try< Memory > memory()
Definition: freebsd.hpp:78
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Exec &_exec)
Definition: fork.hpp:132
std::atomic_bool set
Definition: fork.hpp:241
Try< std::set< pid_t > > pids()
Definition: freebsd.hpp:62
Exec(const std::string &_command)
Definition: fork.hpp:103
Fork(const Option< void(*)()> &_function, const Fork &fork1, const Wait &_wait)
Definition: fork.hpp:141
const T & get() const
Definition: try.hpp:73
constexpr const char * name
Definition: shell.hpp:41
Try< Nothing > ftruncate(int fd, off_t length)
Definition: ftruncate.hpp:26