90 lines
2.1 KiB
C++
90 lines
2.1 KiB
C++
#include <daggy/executors/ForkingExecutor.hpp>
|
|
|
|
#include <array>
|
|
#include <utility>
|
|
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <wait.h>
|
|
#include <poll.h>
|
|
|
|
using namespace daggy::executor;
|
|
|
|
std::string slurp(int fd) {
|
|
std::string result;
|
|
|
|
const ssize_t BUFFER_SIZE = 4096;
|
|
char buffer[BUFFER_SIZE];
|
|
|
|
struct pollfd pfd{.fd = fd, .events = POLLIN, .revents = 0};
|
|
poll(&pfd, 1, 1);
|
|
|
|
while (pfd.revents & POLLIN) {
|
|
ssize_t bytes = read(fd, buffer, BUFFER_SIZE);
|
|
if (bytes == 0) {
|
|
break;
|
|
} else {
|
|
result.append(buffer, bytes);
|
|
}
|
|
pfd.revents = 0;
|
|
poll(&pfd, 1, 1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
daggy::AttemptRecord
|
|
ForkingExecutor::runCommand(std::vector<std::string> cmd) {
|
|
AttemptRecord rec;
|
|
|
|
rec.startTime = Clock::now();
|
|
|
|
// Need to convert the strings
|
|
std::vector<char *> argv;
|
|
for (const auto &s : cmd) {
|
|
argv.push_back(const_cast<char *>(s.c_str()));
|
|
}
|
|
argv.push_back(nullptr);
|
|
|
|
// Create the pipe
|
|
int stdoutPipe[2];
|
|
pipe2(stdoutPipe, O_DIRECT);
|
|
int stderrPipe[2];
|
|
pipe2(stderrPipe, O_DIRECT);
|
|
|
|
pid_t child = fork();
|
|
if (child < 0) {
|
|
throw std::runtime_error("Unable to fork child");
|
|
} else if (child == 0) { // child
|
|
while ((dup2(stdoutPipe[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
|
|
while ((dup2(stderrPipe[1], STDERR_FILENO) == -1) && (errno == EINTR)) {}
|
|
close(stdoutPipe[0]);
|
|
close(stderrPipe[0]);
|
|
execvp(argv[0], argv.data());
|
|
exit(-1);
|
|
}
|
|
|
|
std::atomic<bool> running = true;
|
|
std::thread stdoutReader([&]() { while (running) rec.output.append(slurp(stdoutPipe[0])); });
|
|
std::thread stderrReader([&]() { while (running) rec.error.append(slurp(stderrPipe[0])); });
|
|
|
|
int rc = 0;
|
|
waitpid(child, &rc, 0);
|
|
running = false;
|
|
|
|
rec.stopTime = Clock::now();
|
|
if (WIFEXITED(rc)) {
|
|
rec.rc = WEXITSTATUS(rc);
|
|
} else {
|
|
rec.rc = -1;
|
|
}
|
|
|
|
stdoutReader.join();
|
|
stderrReader.join();
|
|
|
|
close(stdoutPipe[0]);
|
|
close(stderrPipe[0]);
|
|
|
|
return rec;
|
|
}
|