diff --git a/rpcsx/core/include/rx/watchdog.hpp b/rpcsx/core/include/rx/watchdog.hpp index b12cdf2f5..ba3334153 100644 --- a/rpcsx/core/include/rx/watchdog.hpp +++ b/rpcsx/core/include/rx/watchdog.hpp @@ -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 diff --git a/rpcsx/core/src/watchdog.cpp b/rpcsx/core/src/watchdog.cpp index 85b9dd5d3..1e8c14726 100644 --- a/rpcsx/core/src/watchdog.cpp +++ b/rpcsx/core/src/watchdog.cpp @@ -1,8 +1,10 @@ #include "rx/watchdog.hpp" #include "gpu/DeviceCtl.hpp" #include "orbis/KernelContext.hpp" +#include #include #include +#include #include #include #include @@ -21,9 +23,11 @@ static std::atomic g_runGpuRequested; static pid_t g_watchdogPid; static pid_t g_gpuPid; static char g_shmPath[256]; +static std::vector 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(info->si_value.sival_int)) { + auto rawMessage = std::bit_cast(info->si_value.sival_ptr); + auto id = static_cast(static_cast(rawMessage)); + auto data = static_cast(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(id), + .sival_ptr = std::bit_cast( + ((static_cast(data) << 32) | + static_cast(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 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); } diff --git a/rpcsx/main.cpp b/rpcsx/main.cpp index a69604caf..471c7c51b 100644 --- a/rpcsx/main.cpp +++ b/rpcsx/main.cpp @@ -705,6 +705,7 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path, } orbis::kfree(flag, sizeof(*flag)); + rx::attachProcess(hostPid); return {}; } diff --git a/rpcsx/ops.cpp b/rpcsx/ops.cpp index 177c8d6f7..9ea5e5e5c 100644 --- a/rpcsx/ops.cpp +++ b/rpcsx/ops.cpp @@ -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 address, orbis::ptr 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 address, orbis::SysResult open(orbis::Thread *thread, orbis::ptr path, orbis::sint flags, orbis::sint mode, orbis::Ref *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 path) { orbis::SysResult rename(Thread *thread, ptr from, ptr 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 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);