watchdog: track all child processes

This commit is contained in:
DH 2024-10-14 19:20:36 +03:00
parent 0cca4b83be
commit 0e8a918f45
4 changed files with 62 additions and 12 deletions

View file

@ -8,5 +8,6 @@ const char *getShmPath();
std::filesystem::path getShmGuestPath(std::string_view path);
void createGpuDevice();
void shutdown();
void attachProcess(int pid);
int startWatchdog();
} // namespace rx

View file

@ -1,8 +1,10 @@
#include "rx/watchdog.hpp"
#include "gpu/DeviceCtl.hpp"
#include "orbis/KernelContext.hpp"
#include <bit>
#include <chrono>
#include <csignal>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
@ -21,9 +23,11 @@ static std::atomic<bool> g_runGpuRequested;
static pid_t g_watchdogPid;
static pid_t g_gpuPid;
static char g_shmPath[256];
static std::vector<int> g_attachedProcesses;
enum class MessageId {
RunGPU,
AttachProcess,
};
static void runGPU() {
@ -61,10 +65,16 @@ static void runGPU() {
}
static void handleManagementSignal(siginfo_t *info) {
switch (static_cast<MessageId>(info->si_value.sival_int)) {
auto rawMessage = std::bit_cast<std::uintptr_t>(info->si_value.sival_ptr);
auto id = static_cast<MessageId>(static_cast<std::uint32_t>(rawMessage));
auto data = static_cast<std::uint32_t>(rawMessage >> 32);
switch (id) {
case MessageId::RunGPU:
g_runGpuRequested = true;
break;
case MessageId::AttachProcess:
g_attachedProcesses.push_back(data);
break;
}
}
@ -78,10 +88,12 @@ static void handle_watchdog_signal(int sig, siginfo_t *info, void *) {
}
}
static void sendMessage(MessageId id) {
static void sendMessage(MessageId id, std::uint32_t data) {
sigqueue(g_watchdogPid, SIGUSR1,
{
.sival_int = static_cast<int>(id),
.sival_ptr = std::bit_cast<void *>(
((static_cast<std::uintptr_t>(data) << 32) |
static_cast<std::uintptr_t>(id))),
});
}
@ -90,9 +102,11 @@ std::filesystem::path rx::getShmGuestPath(std::string_view path) {
return std::format("{}/guest/{}", getShmPath(), path);
}
void rx::createGpuDevice() { sendMessage(MessageId::RunGPU); }
void rx::createGpuDevice() { sendMessage(MessageId::RunGPU, 0); }
void rx::shutdown() { kill(g_watchdogPid, SIGQUIT); }
void rx::attachProcess(int pid) { sendMessage(MessageId::AttachProcess, pid); }
static void killProcesses(std::vector<int> list) {
int iteration = 0;
while (!list.empty()) {
@ -161,6 +175,18 @@ int rx::startWatchdog() {
std::exit(-1);
}
if (sigaction(SIGHUP, &act, nullptr)) {
perror("Error sigaction:");
std::exit(-1);
}
sigset_t sigSet;
sigemptyset(&sigSet);
sigaddset(&sigSet, SIGUSR1);
sigaddset(&sigSet, SIGINT);
sigaddset(&sigSet, SIGQUIT);
sigaddset(&sigSet, SIGHUP);
int stat = 0;
while (true) {
auto childPid = wait(&stat);
@ -185,10 +211,31 @@ int rx::startWatchdog() {
g_runGpuRequested = false;
runGPU();
}
if (childPid <= 0) {
continue;
}
pthread_sigmask(SIG_BLOCK, &sigSet, nullptr);
for (std::size_t i = 0; i < g_attachedProcesses.size();) {
if (g_attachedProcesses[i] != childPid) {
continue;
}
if (i + 1 != g_attachedProcesses.size()) {
std::swap(g_attachedProcesses[i], g_attachedProcesses.back());
}
g_attachedProcesses.pop_back();
}
pthread_sigmask(SIG_UNBLOCK, &sigSet, nullptr);
}
pthread_sigmask(SIG_BLOCK, &sigSet, nullptr);
std::filesystem::remove_all(g_shmPath);
killProcesses({initProcessPid, g_gpuPid});
g_attachedProcesses.push_back(initProcessPid);
g_attachedProcesses.push_back(g_gpuPid);
killProcesses(g_attachedProcesses);
::wait(nullptr);
std::_Exit(stat);
}

View file

@ -705,6 +705,7 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
}
orbis::kfree(flag, sizeof(*flag));
rx::attachProcess(hostPid);
return {};
}

View file

@ -16,6 +16,7 @@
#include "orbis/utils/Logs.hpp"
#include "orbis/utils/Rc.hpp"
#include "orbis/vm.hpp"
#include "rx/watchdog.hpp"
#include "thread.hpp"
#include "vfs.hpp"
#include "vm.hpp"
@ -287,7 +288,7 @@ orbis::SysResult
query_memory_protection(orbis::Thread *thread, orbis::ptr<void> address,
orbis::ptr<MemoryProtection> protection) {
if (vm::queryProtection(address, &protection->startAddress,
&protection->endAddress, &protection->prot)) {
&protection->endAddress, &protection->prot)) {
return {};
}
return ErrorCode::INVAL;
@ -296,8 +297,7 @@ query_memory_protection(orbis::Thread *thread, orbis::ptr<void> address,
orbis::SysResult open(orbis::Thread *thread, orbis::ptr<const char> path,
orbis::sint flags, orbis::sint mode,
orbis::Ref<orbis::File> *file) {
return vfs::open(getAbsolutePath(path, thread), flags, mode, file,
thread);
return vfs::open(getAbsolutePath(path, thread), flags, mode, file, thread);
}
orbis::SysResult shm_open(orbis::Thread *thread, const char *path,
@ -320,8 +320,8 @@ orbis::SysResult rmdir(Thread *thread, ptr<const char> path) {
orbis::SysResult rename(Thread *thread, ptr<const char> from,
ptr<const char> to) {
ORBIS_LOG_TODO(__FUNCTION__, from, to);
return vfs::rename(getAbsolutePath(from, thread),
getAbsolutePath(to, thread), thread);
return vfs::rename(getAbsolutePath(from, thread), getAbsolutePath(to, thread),
thread);
}
orbis::SysResult blockpool_open(orbis::Thread *thread,
@ -480,8 +480,7 @@ orbis::SysResult dynlib_load_prx(orbis::Thread *thread,
{
orbis::Ref<orbis::File> file;
if (auto result = vfs::open(path, 0, 0, &file, thread);
result.isError()) {
if (auto result = vfs::open(path, 0, 0, &file, thread); result.isError()) {
return result;
}
}
@ -762,6 +761,8 @@ SysResult fork(Thread *thread, slong flags) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
rx::attachProcess(hostPid);
kfree(flag, sizeof(*flag));
thread->tproc->event.emit(orbis::kEvFiltProc, orbis::kNoteFork, childPid);