1 #include "ForkAndExec.hpp"
10 static inline int setfl(int fd
, int newflags
) {
11 auto oldflags
= fcntl(fd
, F_GETFL
);
12 return fcntl(fd
, F_SETFL
, oldflags
| newflags
);
14 static inline int pipe2(int pipefd
[2], int flags
) {
21 rc
= setfl(pipefd
[0], flags
);
25 return setfl(pipefd
[1], flags
);
29 ForkAndExec::ForkAndExec(const char *binary_
, char **argv_
)
37 ForkAndExec::~ForkAndExec() {
38 for (auto &pipe
: {ready
, pipes
}) {
39 for (auto m
: {READ
, WRITE
}) {
45 int ForkAndExec::createPipe() {
46 if (pipes
[mode::READ
] == -1) {
47 if(pipe2(pipes
, O_NONBLOCK
)) {
48 perror("ForkAndExec pipe()");
53 return pipes
[mode::READ
];
56 pid_t
ForkAndExec::operator()() {
57 if (!prepareExecReadyPipe()) {
61 switch (pid_t pid
= fork()) {
63 closePipe(pipes
[mode::READ
]);
66 perror("ForkAndExec exec()");
70 perror("ForkAndExec fork()");
74 pipes
[mode::READ
] = -1;
75 closePipe(pipes
[mode::WRITE
]);
81 bool ForkAndExec::prepareExecReadyPipe() {
82 if (ready
[mode::READ
] == -1) {
83 if (pipe2(ready
, O_CLOEXEC
| O_NONBLOCK
)) {
84 perror("ForkAndExec pipe()");
87 closePipe(ready
[mode::WRITE
]);
93 void ForkAndExec::prepareOutputPipe() {
94 if (pipes
[mode::WRITE
] != -1) {
95 if (0 > dup2(pipes
[mode::WRITE
], STDERR_FILENO
) ||
96 0 > dup2(pipes
[mode::WRITE
], STDOUT_FILENO
)) {
97 perror("ForkAndExec dup()");
102 void ForkAndExec::closePipe(int &fd
) {
109 void ForkAndExec::pollExecReadyPipe() {
113 if (0 == read(ready
[mode::READ
], &c
, 1)) {
116 this_thread::sleep_for(100ms
);
117 } while (errno
== EAGAIN
&& n
--);
119 pollfd fd
{ready
[mode::READ
], 0, 0};
120 if (1 > poll(&fd
, 1, 5000)) {
121 cerr
<< "exec() timed out" << endl
;