flush [ci skip]
[awesomized/libmemcached] / testing / lib / ForkAndExec.cpp
1 #include "ForkAndExec.hpp"
2
3 #include <cerrno>
4 #include <cstdio>
5
6 #include <fcntl.h>
7 #include <sys/poll.h>
8 #include <unistd.h>
9
10 ForkAndExec::ForkAndExec(const char *binary_, char **argv_)
11 : binary{binary_}
12 , argv{argv_}
13 {
14 if (pipe2(pipes, O_CLOEXEC|O_NONBLOCK)) {
15 int error = errno;
16 perror("Server::start pipe2()");
17 throw system_error(error, system_category());
18 }
19 }
20
21 ForkAndExec::~ForkAndExec() {
22 if (pipes[0] != -1) {
23 close(pipes[0]);
24 }
25 if (pipes[1] != -1) {
26 close(pipes[1]);
27 }
28 }
29
30 optional<pid_t> ForkAndExec::operator()() {
31 if (pipes[0] == -1) {
32 return {};
33 }
34 if (pipes[1] != -1) {
35 close(pipes[1]);
36 pipes[1] = -1;
37 }
38
39 switch (pid_t pid = fork()) {
40 case 0:
41 execvp(binary, argv);
42 [[fallthrough]];
43 case -1:
44 perror("fork() && exec()");
45 return {};
46
47 default:
48 pollfd fd{pipes[0], 0, 0};
49 if (1 > poll(&fd, 1, 5000)) {
50 cerr << "exec() timed out" << endl;
51 }
52 return pid;
53 }
54 }