1 #include "ForkAndExec.hpp"
11 static inline int setfl(int fd
, int newflags
) {
12 auto oldflags
= fcntl(fd
, F_GETFL
);
13 return fcntl(fd
, F_SETFL
, oldflags
| newflags
);
15 static inline int pipe2(int pipefd
[2], int flags
) {
22 rc
= setfl(pipefd
[0], flags
);
26 return setfl(pipefd
[1], flags
);
30 ForkAndExec::ForkAndExec(const char *binary_
, char **argv_
)
38 ForkAndExec::~ForkAndExec() {
39 for (auto &pipe
: {ready
, pipes
}) {
40 for (auto m
: {READ
, WRITE
}) {
46 int ForkAndExec::createPipe() {
47 if (pipes
[mode::READ
] == -1) {
48 if(pipe2(pipes
, O_NONBLOCK
)) {
49 perror("ForkAndExec pipe()");
54 return pipes
[mode::READ
];
57 pid_t
ForkAndExec::operator()() {
58 if (!prepareExecReadyPipe()) {
62 switch (pid_t pid
= fork()) {
64 closePipe(pipes
[mode::READ
]);
67 perror("ForkAndExec exec()");
71 perror("ForkAndExec fork()");
75 pipes
[mode::READ
] = -1;
76 closePipe(pipes
[mode::WRITE
]);
82 bool ForkAndExec::prepareExecReadyPipe() {
83 if (ready
[mode::READ
] == -1) {
84 if (pipe2(ready
, O_CLOEXEC
| O_NONBLOCK
)) {
85 perror("ForkAndExec pipe()");
88 closePipe(ready
[mode::WRITE
]);
94 void ForkAndExec::prepareOutputPipe() {
95 if (pipes
[mode::WRITE
] != -1) {
96 if (0 > dup2(pipes
[mode::WRITE
], STDERR_FILENO
) ||
97 0 > dup2(pipes
[mode::WRITE
], STDOUT_FILENO
)) {
98 perror("ForkAndExec dup()");
103 void ForkAndExec::closePipe(int &fd
) {
110 void ForkAndExec::pollExecReadyPipe() {
114 if (0 == read(ready
[mode::READ
], &c
, 1)) {
117 this_thread::sleep_for(100ms
);
118 } while (errno
== EAGAIN
&& n
--);
120 pollfd fd
{ready
[mode::READ
], 0, 0};
121 if (1 > poll(&fd
, 1, 5000)) {
122 cerr
<< "exec() timed out" << endl
;