You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.1 KiB
89 lines
3.1 KiB
#include "runner.hpp"
|
|
|
|
#include <array>
|
|
#include <cerrno>
|
|
#include <poll.h>
|
|
#include <spawn.h>
|
|
#include <system_error>
|
|
#include <unistd.h>
|
|
#include <wait.h>
|
|
|
|
namespace sk {
|
|
run_result runner::run_blocking(const program &program) {
|
|
int in_pipe[2];
|
|
int out_pipe[2];
|
|
int err_pipe[2];
|
|
if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1 || pipe(err_pipe) == -1) {
|
|
throw std::system_error{errno, std::generic_category()};
|
|
}
|
|
|
|
posix_spawn_file_actions_t actions;
|
|
posix_spawn_file_actions_init(&actions);
|
|
posix_spawn_file_actions_addclose(&actions, in_pipe[1]);
|
|
posix_spawn_file_actions_addclose(&actions, out_pipe[0]);
|
|
posix_spawn_file_actions_addclose(&actions, err_pipe[0]);
|
|
posix_spawn_file_actions_adddup2(&actions, in_pipe[0], 0);
|
|
posix_spawn_file_actions_adddup2(&actions, out_pipe[1], 1);
|
|
posix_spawn_file_actions_adddup2(&actions, err_pipe[1], 2);
|
|
posix_spawn_file_actions_addclose(&actions, in_pipe[0]);
|
|
posix_spawn_file_actions_addclose(&actions, out_pipe[1]);
|
|
posix_spawn_file_actions_addclose(&actions, err_pipe[1]);
|
|
const char *const args[] = {"docker",
|
|
"run",
|
|
"--rm",
|
|
"-i",
|
|
"--pull=never",
|
|
"--cap-drop=ALL",
|
|
"--network=none",
|
|
"--memory=64m",
|
|
"--memory-swap=64m",
|
|
"--pids-limit=128",
|
|
program.image.c_str(),
|
|
nullptr};
|
|
pid_t pid;
|
|
int exit_code;
|
|
if (posix_spawnp(&pid, args[0], &actions, nullptr,
|
|
const_cast<char *const *>(args), nullptr) != 0) {
|
|
throw std::system_error{errno, std::generic_category()};
|
|
}
|
|
|
|
close(in_pipe[0]);
|
|
close(out_pipe[1]);
|
|
close(err_pipe[1]);
|
|
|
|
write(in_pipe[1], program.code.data(), program.code.size());
|
|
close(in_pipe[1]);
|
|
|
|
std::array<char, 1024> buffer{};
|
|
std::string out;
|
|
std::string err;
|
|
std::array<pollfd, 2> plist = {pollfd{out_pipe[0], POLLIN, 0},
|
|
pollfd{err_pipe[0], POLLIN, 0}};
|
|
while (poll(plist.data(), plist.size(), /*timeout*/ -1) > 0) {
|
|
if (plist[0].revents & POLLIN) {
|
|
ssize_t bytes_read =
|
|
read(out_pipe[0], buffer.data(), buffer.size());
|
|
if (bytes_read == -1) {
|
|
throw std::system_error{errno, std::generic_category()};
|
|
}
|
|
out.append(buffer.data(), bytes_read);
|
|
} else if (plist[1].revents & POLLIN) {
|
|
ssize_t bytes_read =
|
|
read(err_pipe[0], buffer.data(), buffer.size());
|
|
if (bytes_read == -1) {
|
|
throw std::system_error{errno, std::generic_category()};
|
|
}
|
|
err.append(buffer.data(), bytes_read);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
waitpid(pid, &exit_code, 0);
|
|
close(out_pipe[0]);
|
|
close(err_pipe[0]);
|
|
|
|
posix_spawn_file_actions_destroy(&actions);
|
|
return run_result{out, err};
|
|
}
|
|
}
|