1 #include "ForkAndExec.hpp"
2 #include "p9y/poll.hpp"
12 static inline int setfl(int fd
, int newflags
) {
13 auto oldflags
= fcntl(fd
, F_GETFL
);
14 return fcntl(fd
, F_SETFL
, oldflags
| newflags
);
16 static inline int pipe2(int pipefd
[2], int flags
) {
23 rc
= setfl(pipefd
[0], flags
);
27 return setfl(pipefd
[1], flags
);
31 ForkAndExec::ForkAndExec(const char *binary_
, char **argv_
)
39 ForkAndExec::~ForkAndExec() {
40 for (auto &pipe
: {ready
, pipes
}) {
41 for (auto m
: {READ
, WRITE
}) {
47 int ForkAndExec::createPipe() {
48 if (pipes
[mode::READ
] == -1) {
49 if(pipe2(pipes
, O_NONBLOCK
)) {
50 perror("ForkAndExec pipe()");
55 return pipes
[mode::READ
];
58 pid_t
ForkAndExec::operator()() {
59 if (!prepareExecReadyPipe()) {
63 switch (pid_t pid
= fork()) {
65 closePipe(pipes
[mode::READ
]);
68 perror("ForkAndExec exec()");
72 perror("ForkAndExec fork()");
76 pipes
[mode::READ
] = -1;
77 closePipe(pipes
[mode::WRITE
]);
83 bool ForkAndExec::prepareExecReadyPipe() {
84 if (ready
[mode::READ
] == -1) {
85 if (pipe2(ready
, O_CLOEXEC
| O_NONBLOCK
)) {
86 perror("ForkAndExec pipe()");
89 closePipe(ready
[mode::WRITE
]);
95 void ForkAndExec::prepareOutputPipe() {
96 if (pipes
[mode::WRITE
] != -1) {
97 if (0 > dup2(pipes
[mode::WRITE
], STDERR_FILENO
) ||
98 0 > dup2(pipes
[mode::WRITE
], STDOUT_FILENO
)) {
99 perror("ForkAndExec dup()");
104 void ForkAndExec::closePipe(int &fd
) {
111 void ForkAndExec::pollExecReadyPipe() {
115 if (0 == read(ready
[mode::READ
], &c
, 1)) {
118 this_thread::sleep_for(100ms
);
119 } while (errno
== EAGAIN
&& n
--);
121 pollfd fd
{ready
[mode::READ
], 0, 0};
122 if (1 > poll(&fd
, 1, 5000)) {
123 cerr
<< "exec() timed out" << endl
;