753e06ee88f680104886cc9cc1140f5e9324ef72
1 #include "ForkAndExec.hpp"
13 static inline int setfl(int fd
, int newflags
) {
14 auto oldflags
= fcntl(fd
, F_GETFL
);
15 return fcntl(fd
, F_SETFL
, oldflags
| newflags
);
17 static inline int pipe2(int pipefd
[2], int flags
) {
24 rc
= setfl(pipefd
[0], flags
);
28 return setfl(pipefd
[1], flags
);
32 ForkAndExec::ForkAndExec(const char *binary_
, char **argv_
)
40 ForkAndExec::~ForkAndExec() {
41 for (auto &pipe
: {ready
, pipes
}) {
42 for (auto m
: {READ
, WRITE
}) {
48 int ForkAndExec::createPipe() {
49 if (pipes
[mode::READ
] == -1) {
50 if(pipe2(pipes
, O_NONBLOCK
)) {
51 perror("ForkAndExec pipe()");
56 return pipes
[mode::READ
];
59 pid_t
ForkAndExec::operator()() {
60 if (!prepareExecReadyPipe()) {
64 switch (pid_t pid
= fork()) {
66 closePipe(pipes
[mode::READ
]);
69 perror("ForkAndExec exec()");
73 perror("ForkAndExec fork()");
77 pipes
[mode::READ
] = -1;
78 closePipe(pipes
[mode::WRITE
]);
84 bool ForkAndExec::prepareExecReadyPipe() {
85 if (ready
[mode::READ
] == -1) {
86 if (pipe2(ready
, O_CLOEXEC
| O_NONBLOCK
)) {
87 perror("ForkAndExec pipe()");
90 closePipe(ready
[mode::WRITE
]);
96 void ForkAndExec::prepareOutputPipe() {
97 if (pipes
[mode::WRITE
] != -1) {
98 if (0 > dup2(pipes
[mode::WRITE
], STDERR_FILENO
) ||
99 0 > dup2(pipes
[mode::WRITE
], STDOUT_FILENO
)) {
100 perror("ForkAndExec dup()");
105 void ForkAndExec::closePipe(int &fd
) {
112 void ForkAndExec::pollExecReadyPipe() {
116 if (0 == read(ready
[mode::READ
], &c
, 1)) {
119 this_thread::sleep_for(100ms
);
120 } while (errno
== EAGAIN
&& n
--);
122 pollfd fd
{ready
[mode::READ
], 0, 0};
123 if (1 > poll(&fd
, 1, 5000)) {
124 cerr
<< "exec() timed out" << endl
;