glove/tests/container/cgroup_probe_agent.cpp
2026-07-19 21:06:11 -04:00

98 lines
2.3 KiB
C++

#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#include <cerrno>
#include <csignal>
#include <cstddef>
#include <cstdlib>
#include <string_view>
namespace {
[[noreturn]] void cpu_pressure() {
volatile unsigned int counter = 0;
for (;;) {
counter = counter + 1U;
}
}
[[noreturn]] void memory_pressure(std::size_t bytes) {
void* memory =
::mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (memory == MAP_FAILED) {
std::_Exit(30);
}
auto* data = static_cast<volatile unsigned char*>(memory);
for (std::size_t offset = 0; offset < bytes; offset += 4096) {
data[offset] = 1;
}
std::_Exit(31);
}
[[noreturn]] void pid_pressure() {
const ::pid_t helper = ::fork();
if (helper == 0) {
::pause();
std::_Exit(0);
}
if (helper < 0) {
std::_Exit(20);
}
errno = 0;
const ::pid_t denied = ::fork();
const bool bounded = denied < 0 && errno == EAGAIN;
if (denied == 0) {
std::_Exit(21);
}
if (denied > 0) {
(void)::kill(denied, SIGKILL);
(void)::waitpid(denied, nullptr, 0);
}
(void)::kill(helper, SIGKILL);
(void)::waitpid(helper, nullptr, 0);
std::_Exit(bounded ? 0 : 22);
}
[[noreturn]] void sleep_until_signal() {
for (;;) {
::pause();
}
}
} // namespace
auto main(int argc, char** argv) -> int {
if (argc < 2) {
return 2;
}
const std::string_view mode{argv[1]};
if (mode == "cpu") {
cpu_pressure();
}
if (mode == "memory") {
if (argc != 3) {
return 2;
}
char* end = nullptr;
const auto bytes = std::strtoull(argv[2], &end, 10);
if (end == argv[2] || *end != '\0' || bytes == 0) {
return 2;
}
memory_pressure(static_cast<std::size_t>(bytes));
}
if (mode == "pids") {
pid_pressure();
}
if (mode == "sleep") {
sleep_until_signal();
}
if (mode == "exit" && argc == 3) {
char* end = nullptr;
const long code = std::strtol(argv[2], &end, 10);
if (end != argv[2] && *end == '\0' && code >= 0 && code <= 255) {
return static_cast<int>(code);
}
}
return 2;
}