mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-27 09:00:57 +01:00
Extends SignalDelegator duty
It needs to track guest SigAltAction and have its own definitions for sigaction and sa_mask. sa_mask specifically is defined differently between the kernel and glibc. Also fixes some issues with the SignalDelegator that posix tests found
This commit is contained in:
1 parent
211aebcfa4
commit
f705baf2f0
4 files changed
+287
-62
No files matched your search
+3
-2
@@ -126,8 +126,7 @@ namespace DefaultFallbackCore {
|
||||
}
|
||||
|
||||
namespace FEXCore::Context {
|
||||
Context::Context()
|
||||
: SignalDelegation {this} {
|
||||
Context::Context() {
|
||||
FallbackCPUFactory = FEXCore::Core::DefaultFallbackCore::CPUCreationFactory;
|
||||
#ifdef BLOCKSTATS
|
||||
BlockData = std::make_unique<FEXCore::BlockSamplingData>();
|
||||
@@ -870,6 +869,8 @@ namespace FEXCore::Context {
|
||||
--IdleWaitRefCount;
|
||||
IdleWaitCV.notify_all();
|
||||
|
||||
SignalDelegation.UninstallTLSState(Thread);
|
||||
|
||||
Thread->State.RunningEvents.WaitingToStart = false;
|
||||
Thread->State.RunningEvents.Running = false;
|
||||
}
|
||||
|
||||
+241
-49
@@ -1,16 +1,26 @@
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/InternalThreadState.h"
|
||||
#include "Interface/Core/SignalDelegator.h"
|
||||
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <LogManager.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace FEXCore {
|
||||
constexpr static uint32_t SS_AUTODISARM = (1U << 31);
|
||||
constexpr static uint32_t X86_MINSIGSTKSZ = 0x2000U;
|
||||
|
||||
// We can only have one delegator per process
|
||||
static SignalDelegator *GlobalDelegator{};
|
||||
|
||||
struct ThreadState {
|
||||
FEXCore::Core::InternalThreadState *Thread{};
|
||||
void *AltStackPtr{};
|
||||
stack_t GuestAltStack{};
|
||||
// Guest signal sa_mask is per thread!
|
||||
SignalDelegator::GuestSAMask Guest_sa_mask[SignalDelegator::MAX_SIGNALS]{};
|
||||
uint32_t CurrentSignal{};
|
||||
};
|
||||
|
||||
thread_local ThreadState ThreadData{};
|
||||
@@ -32,27 +42,48 @@ namespace FEXCore {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t SigIsMember(SignalDelegator::GuestSAMask *Set, int Signal) {
|
||||
// Signal 0 isn't real, so everything is offset by one inside the set
|
||||
Signal -= 1;
|
||||
return (Set->Val >> Signal) & 1;
|
||||
}
|
||||
|
||||
void SignalDelegator::SetCurrentSignal(uint32_t Signal) {
|
||||
ThreadData.CurrentSignal = Signal;
|
||||
}
|
||||
|
||||
void SignalDelegator::HandleSignal(int Signal, void *Info, void *UContext) {
|
||||
// Let the host take first stab at handling the signal
|
||||
|
||||
siginfo_t *SigInfo = static_cast<siginfo_t*>(Info);
|
||||
auto Thread = ThreadData.Thread;
|
||||
SignalHandler &Handler = HostHandlers[Signal];
|
||||
|
||||
if (!Thread) {
|
||||
LogMan::Msg::E("Thread has received a signal and hasn't registered itself with the delegate! Programming error!");
|
||||
exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Handler.Handler &&
|
||||
Handler.Handler(Thread, Signal, Info, UContext)) {
|
||||
// If the host handler handled the fault then we can continue now
|
||||
return;
|
||||
}
|
||||
|
||||
// If the signal was sent by the user with kill then we can't block it
|
||||
// If it was sent by raise() then we /can/ block it
|
||||
bool SentByUser = SigInfo->si_code <= 0;
|
||||
|
||||
if (Signal == SIGCHLD) {
|
||||
// Do some special handling around this signal
|
||||
// If the guest has a signal handler installed with SA_NOCLDSTOP or SA_NOCHLDWAIT then
|
||||
// handle carefully
|
||||
if (Handler.GuestAction.sa_flags & SA_NOCLDSTOP) {
|
||||
// No signal is generated in this case
|
||||
// just safely return
|
||||
// XXX: If this was a child that exited then don't deliver the signal
|
||||
// If called from signal then it still need to be delivered
|
||||
// Handle this
|
||||
if (Handler.GuestAction.sa_flags & SA_NOCLDSTOP &&
|
||||
!SentByUser) {
|
||||
// If we were sent the signal from kill, tkill, or tgkill
|
||||
// then si_code is set to SI_TKILL and should be delivered to the guest
|
||||
// Otherwise if NOCLDSTOP is set without this code, just drop the signal
|
||||
return;
|
||||
}
|
||||
|
||||
if (Handler.GuestAction.sa_flags & SA_NOCLDWAIT) {
|
||||
@@ -63,25 +94,28 @@ namespace FEXCore {
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Setup our state to jump back in to the JIT at the guest handler's location
|
||||
// TLS is safe on x86-64 and AArch64 hosts
|
||||
if (!Thread) {
|
||||
LogMan::Msg::E("Thread has received a signal and hasn't registered itself with the delegate! Programming error!");
|
||||
if (SigIsMember(&ThreadData.Guest_sa_mask[ThreadData.CurrentSignal], Signal)) {
|
||||
// If we are in a signal and our signal mask is blocking this signal then ignore it
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadData.CurrentSignal = Signal;
|
||||
|
||||
// We have an emulation thread pointer, we can now modify its state
|
||||
if (Handler.GuestAction.sigaction_handler.handler == SIG_DFL) {
|
||||
// XXX: Maybe this should actually go down guest handler state?
|
||||
signal(Signal, SIG_DFL);
|
||||
return;
|
||||
}
|
||||
else if (Handler.GuestAction.sigaction_handler.handler == SIG_IGN) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// We have an emulation thread pointer, we can now modify its state
|
||||
if (Handler.GuestAction.sa_handler == SIG_DFL) {
|
||||
// XXX: Maybe this should actually go down guest handler state?
|
||||
signal(Signal, SIG_DFL);
|
||||
if (Handler.GuestHandler &&
|
||||
Handler.GuestHandler(Thread, Signal, Info, UContext, &Handler.GuestAction, &ThreadData.GuestAltStack)) {
|
||||
return;
|
||||
}
|
||||
else if (Handler.GuestAction.sa_handler == SIG_IGN) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// XXX: Handle the guest signal and return here
|
||||
ERROR_AND_DIE("Unhandled guest exception");
|
||||
}
|
||||
ERROR_AND_DIE("Unhandled guest exception");
|
||||
}
|
||||
|
||||
// Unhandled crash
|
||||
@@ -99,38 +133,90 @@ namespace FEXCore {
|
||||
}
|
||||
}
|
||||
|
||||
void SignalDelegator::InstallHostThunk(int Signal) {
|
||||
bool SignalDelegator::InstallHostThunk(int Signal) {
|
||||
SignalHandler &SignalHandler = HostHandlers[Signal];
|
||||
// If the host thunk is already installed for this, just return
|
||||
if (HostHandlers[Signal].Installed) {
|
||||
return;
|
||||
if (SignalHandler.Installed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now install the thunk handler
|
||||
struct sigaction act{};
|
||||
act.sa_sigaction = &SignalHandlerThunk;
|
||||
act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||
SignalHandler.HostAction.sa_sigaction = &SignalHandlerThunk;
|
||||
SignalHandler.HostAction.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK;
|
||||
|
||||
if (SignalHandler.GuestAction.sa_flags & SA_NODEFER) {
|
||||
// If the guest is using NODEFER then make sure to set it for the host as well
|
||||
SignalHandler.HostAction.sa_flags |= SA_NODEFER;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: This isn't quite as straightforward as a memcmp
|
||||
* There are conflicting definitions between sigset_t and __sigset_t causing problems here
|
||||
sigset_t EmptySet{};
|
||||
sigemptyset(&EmptySet);
|
||||
if (SignalHandler.GuestAction.sa_mask != EmptySet) {
|
||||
// If the guest has masked some signals then we need to also mask those signals
|
||||
SignalHandler.HostAction.sa_mask = SignalHandler.GuestAction.sa_mask;
|
||||
|
||||
// If the guest tried masking SIGILL or SIGBUS then too bad, we actually need this on the host
|
||||
sigdelset(SignalHandler.HostAction.sa_mask, SIGILL);
|
||||
sigdelset(SignalHandler.HostAction.sa_mask, SIGBUS);
|
||||
}
|
||||
*/
|
||||
|
||||
// We don't care about the previous handler in this case
|
||||
int Result = sigaction(Signal, &act, &HostHandlers[Signal].OldAction);
|
||||
int Result = sigaction(Signal, &SignalHandler.HostAction, &SignalHandler.OldAction);
|
||||
if (Result < 0) {
|
||||
LogMan::Msg::D("Failed to install host signal thunk for signal %d: %s", Signal, strerror(errno));
|
||||
LogMan::Msg::E("Failed to install host signal thunk for signal %d: %s", Signal, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
SignalHandler.Installed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SignalDelegator::UpdateHostThunk(int Signal) {
|
||||
SignalHandler &SignalHandler = HostHandlers[Signal];
|
||||
bool Changed{};
|
||||
|
||||
// This only gets called if a guest thunk was already installed and we need to check if we need to update the flags or signal mask
|
||||
if ((SignalHandler.GuestAction.sa_flags ^ SignalHandler.HostAction.sa_flags) & SA_NODEFER) {
|
||||
// NODEFER changed, we need to update this
|
||||
SignalHandler.HostAction.sa_flags |= SignalHandler.GuestAction.sa_flags & SA_NODEFER;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
/*
|
||||
if ((SignalHandler.GuestAction.sa_mask ^ SignalHandler.HostAction.sa_mask) & ~(SIGILL | SIGBUS)) {
|
||||
// If the signal ignore mask has updated (avoiding the two we need for the host) then we need to update
|
||||
SignalHandler.HostAction.sa_mask = SignalHandler.GuestAction.sa_mask;
|
||||
sigdelset(SignalHandler.HostAction.sa_mask, SIGILL);
|
||||
sigdelset(SignalHandler.HostAction.sa_mask, SIGBUS);
|
||||
Changed = true;
|
||||
}
|
||||
*/
|
||||
|
||||
if (!Changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
HostHandlers[Signal].Installed = true;
|
||||
// Only update our host signal here
|
||||
int Result = sigaction(Signal, &SignalHandler.HostAction, nullptr);
|
||||
if (Result < 0) {
|
||||
LogMan::Msg::E("Failed to update host signal thunk for signal %d: %s", Signal, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
SignalDelegator::SignalDelegator(FEXCore::Context::Context *ctx)
|
||||
: CTX {ctx} {
|
||||
SignalDelegator::SignalDelegator() {
|
||||
// Register this delegate
|
||||
LogMan::Throw::A(!GlobalDelegator, "Can't register global delegator multiple times!");
|
||||
GlobalDelegator = this;
|
||||
// Signal zero isn't real
|
||||
HostHandlers[0].Installed = true;
|
||||
|
||||
// XXX: Let's just say that these are installed for now
|
||||
// We can't have the guest capturing these yet so it would do nothing
|
||||
// Resulting in Ctrl-C and Ctrl-\ breaking
|
||||
HostHandlers[SIGINT].Installed = true;
|
||||
HostHandlers[SIGQUIT].Installed = true;
|
||||
// We can't capture SIGKILL or SIGSTOP
|
||||
HostHandlers[SIGKILL].Installed = true;
|
||||
HostHandlers[SIGSTOP].Installed = true;
|
||||
|
||||
// glibc reserves these two signals internally
|
||||
// __SIGRTMIN(32) is used for a "cancellation" signal
|
||||
@@ -142,27 +228,63 @@ namespace FEXCore {
|
||||
|
||||
void SignalDelegator::RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) {
|
||||
ThreadData.Thread = Thread;
|
||||
|
||||
// Set up our signal alternative stack
|
||||
// This is per thread rather than per signal
|
||||
ThreadData.AltStackPtr = malloc(SIGSTKSZ);
|
||||
stack_t altstack{};
|
||||
altstack.ss_sp = ThreadData.AltStackPtr;
|
||||
altstack.ss_size = SIGSTKSZ;
|
||||
altstack.ss_flags = 0;
|
||||
LogMan::Throw::A(!!altstack.ss_sp, "Couldn't allocate stack pointer");
|
||||
|
||||
// Register the alt stack
|
||||
int Result = sigaltstack(&altstack, nullptr);
|
||||
if (Result == -1) {
|
||||
LogMan::Msg::E("Failed to install alternative signal stack %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void SignalDelegator::MaskSignals(int how) {
|
||||
void SignalDelegator::UninstallTLSState(FEXCore::Core::InternalThreadState *Thread) {
|
||||
free(ThreadData.AltStackPtr);
|
||||
|
||||
ThreadData.Thread = nullptr;
|
||||
ThreadData.AltStackPtr = nullptr;
|
||||
|
||||
stack_t altstack{};
|
||||
altstack.ss_flags = SS_DISABLE;
|
||||
|
||||
// Uninstall the alt stack
|
||||
int Result = sigaltstack(&altstack, nullptr);
|
||||
if (Result == -1) {
|
||||
LogMan::Msg::E("Failed to uninstall alternative signal stack %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void SignalDelegator::MaskSignals(int how, int Signal) {
|
||||
// If we have a helper thread, we need to mask a significant amount of signals so the an errant thread doesn't receive a signal that it shouldn't
|
||||
sigset_t SignalSet{};
|
||||
sigemptyset(&SignalSet);
|
||||
|
||||
for (int i = 0; i < MAX_SIGNALS; ++i) {
|
||||
// If it is a synchronous signal then don't ignore it
|
||||
if (IsSynchronous(i)) {
|
||||
continue;
|
||||
}
|
||||
if (Signal == -1) {
|
||||
for (int i = 0; i < MAX_SIGNALS; ++i) {
|
||||
// If it is a synchronous signal then don't ignore it
|
||||
if (IsSynchronous(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add this signal to the ignore list
|
||||
sigaddset(&SignalSet, i);
|
||||
// Add this signal to the ignore list
|
||||
sigaddset(&SignalSet, i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sigaddset(&SignalSet, Signal);
|
||||
}
|
||||
|
||||
// Be warned, a thread will inherit the signal mask if created from this thread
|
||||
int Result = pthread_sigmask(how, &SignalSet, nullptr);
|
||||
if (Result != 0) {
|
||||
LogMan::Msg::D("Couldn't register thread to mask signals");
|
||||
LogMan::Msg::E("Couldn't register thread to mask signals");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +296,16 @@ namespace FEXCore {
|
||||
MaskSignals(SIG_UNBLOCK);
|
||||
}
|
||||
|
||||
bool SignalDelegator::BlockSignal(int Signal) {
|
||||
MaskSignals(SIG_BLOCK, Signal);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignalDelegator::UnblockSignal(int Signal) {
|
||||
MaskSignals(SIG_UNBLOCK, Signal);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SignalDelegator::RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func) {
|
||||
// Linux signal handlers are per-process rather than per thread
|
||||
// Multiple threads could be calling in to this
|
||||
@@ -182,7 +314,13 @@ namespace FEXCore {
|
||||
InstallHostThunk(Signal);
|
||||
}
|
||||
|
||||
uint64_t SignalDelegator::RegisterGuestSignalHandler(int Signal, const struct sigaction *Action, struct sigaction *OldAction) {
|
||||
void SignalDelegator::RegisterHostSignalHandlerForGuest(int Signal, HostSignalDelegatorFunctionForGuest Func) {
|
||||
std::lock_guard<std::mutex> lk(HostDelegatorMutex);
|
||||
HostHandlers[Signal].GuestHandler = Func;
|
||||
InstallHostThunk(Signal);
|
||||
}
|
||||
|
||||
uint64_t SignalDelegator::RegisterGuestSignalHandler(int Signal, const GuestSigAction *Action, GuestSigAction *OldAction) {
|
||||
std::lock_guard<std::mutex> lk(GuestDelegatorMutex);
|
||||
|
||||
// If we have an old signal set then give it back
|
||||
@@ -198,10 +336,64 @@ namespace FEXCore {
|
||||
}
|
||||
|
||||
HostHandlers[Signal].GuestAction = *Action;
|
||||
ThreadData.Guest_sa_mask[Signal] = Action->sa_mask;
|
||||
// Only attempt to install a new thunk handler if we were installing a new guest action
|
||||
InstallHostThunk(Signal);
|
||||
if (!InstallHostThunk(Signal)) {
|
||||
UpdateHostThunk(Signal);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t SignalDelegator::RegisterGuestSigAltStack(const stack_t *ss, stack_t *old_ss) {
|
||||
bool UsingAltStack{};
|
||||
uint64_t AltStackBase = reinterpret_cast<uint64_t>(ThreadData.GuestAltStack.ss_sp);
|
||||
uint64_t AltStackEnd = AltStackBase + ThreadData.GuestAltStack.ss_size;
|
||||
uint64_t GuestSP = ThreadData.Thread->State.State.gregs[X86State::REG_RSP];
|
||||
|
||||
if (GuestSP >= AltStackBase &&
|
||||
GuestSP <= AltStackEnd) {
|
||||
UsingAltStack = true;
|
||||
}
|
||||
|
||||
// If we have an old signal set then give it back
|
||||
if (old_ss) {
|
||||
*old_ss = ThreadData.GuestAltStack;
|
||||
|
||||
if (UsingAltStack) {
|
||||
// We are currently operating on the alt stack
|
||||
// Let the guest know
|
||||
old_ss->ss_flags |= SS_ONSTACK;
|
||||
}
|
||||
else {
|
||||
old_ss->ss_flags |= SS_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Now assign the new action
|
||||
if (ss) {
|
||||
// If we tried setting the alt stack while we are using it then throw an error
|
||||
if (UsingAltStack) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
// We need to check for invalid flags
|
||||
// The only flag that can be passed is SS_AUTODISARM
|
||||
if (ss->ss_flags & ~SS_AUTODISARM) {
|
||||
// A flag remained that isn't one of the supported ones?
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// stack size needs to be MINSIGSTKSZ (0x2000)
|
||||
if (ss->ss_size < X86_MINSIGSTKSZ) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ThreadData.GuestAltStack = *ss;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
+41
-7
@@ -15,10 +15,26 @@ namespace Core {
|
||||
|
||||
class SignalDelegator {
|
||||
public:
|
||||
struct __attribute__((packed)) GuestSAMask {
|
||||
uint64_t Val;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) GuestSigAction {
|
||||
union {
|
||||
void (*handler)(int);
|
||||
void (*sigaction)(int, siginfo_t *, void*);
|
||||
} sigaction_handler;
|
||||
|
||||
uint64_t sa_flags;
|
||||
void (*restorer)(void);
|
||||
GuestSAMask sa_mask;
|
||||
};
|
||||
|
||||
// Returns true if the host handled the signal
|
||||
// Arguments are the same as sigaction handler
|
||||
using HostSignalDelegatorFunction = std::function<bool(FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext)>;
|
||||
SignalDelegator(FEXCore::Context::Context *ctx);
|
||||
using HostSignalDelegatorFunctionForGuest = std::function<bool(FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext, GuestSigAction *GuestAction, stack_t *GuestStack)>;
|
||||
SignalDelegator();
|
||||
|
||||
/**
|
||||
* @brief Registers an emulated thread's object to a TLS object
|
||||
@@ -26,6 +42,7 @@ namespace Core {
|
||||
* Required to know which thread has received the signal when it occurs
|
||||
*/
|
||||
static void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread);
|
||||
static void UninstallTLSState(FEXCore::Core::InternalThreadState *Thread);
|
||||
|
||||
/**
|
||||
* @brief Masks a thread from receiving any signals that aren't synchronous
|
||||
@@ -41,37 +58,54 @@ namespace Core {
|
||||
*/
|
||||
static void ResetThreadSignalMask();
|
||||
|
||||
static bool BlockSignal(int Signal);
|
||||
static bool UnblockSignal(int Signal);
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
void RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func);
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal specifically for guest handling
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
void RegisterHostSignalHandlerForGuest(int Signal, HostSignalDelegatorFunctionForGuest Func);
|
||||
|
||||
/**
|
||||
* @brief Allows the guest to register a signal handler that is run after the host attempts to resolve the handler first
|
||||
*/
|
||||
uint64_t RegisterGuestSignalHandler(int Signal, const struct sigaction *Action, struct sigaction *OldAction);
|
||||
uint64_t RegisterGuestSignalHandler(int Signal, const GuestSigAction *Action, struct GuestSigAction *OldAction);
|
||||
|
||||
uint64_t RegisterGuestSigAltStack(const stack_t *ss, stack_t *old_ss);
|
||||
|
||||
// Called from the thunk handler to handle the signal
|
||||
void HandleSignal(int Signal, void *Info, void *UContext);
|
||||
|
||||
private:
|
||||
FEXCore::Context::Context *CTX;
|
||||
void SetCurrentSignal(uint32_t Signal);
|
||||
|
||||
constexpr static size_t MAX_SIGNALS {64};
|
||||
|
||||
private:
|
||||
struct SignalHandler {
|
||||
std::atomic<bool> Installed{};
|
||||
struct sigaction HostAction{};
|
||||
struct sigaction OldAction{};
|
||||
HostSignalDelegatorFunction Handler{};
|
||||
struct sigaction GuestAction{};
|
||||
HostSignalDelegatorFunctionForGuest GuestHandler{};
|
||||
GuestSigAction GuestAction{};
|
||||
};
|
||||
|
||||
SignalHandler HostHandlers[MAX_SIGNALS]{};
|
||||
void InstallHostThunk(int Signal);
|
||||
bool InstallHostThunk(int Signal);
|
||||
void UpdateHostThunk(int Signal);
|
||||
|
||||
std::mutex HostDelegatorMutex;
|
||||
std::mutex GuestDelegatorMutex;
|
||||
|
||||
static void MaskSignals(int how);
|
||||
static void MaskSignals(int how, int Signal = -1);
|
||||
};
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace FEXCore::HLE {
|
||||
|
||||
void RegisterSignals() {
|
||||
REGISTER_SYSCALL_IMPL(rt_sigaction, [](FEXCore::Core::InternalThreadState *Thread, int signum, const struct sigaction *act, struct sigaction *oldact) -> uint64_t {
|
||||
REGISTER_SYSCALL_IMPL(rt_sigaction, [](FEXCore::Core::InternalThreadState *Thread, int signum, const SignalDelegator::GuestSigAction *act, SignalDelegator::GuestSigAction *oldact) -> uint64_t {
|
||||
return Thread->CTX->SignalDelegation.RegisterGuestSignalHandler(signum, act, oldact);
|
||||
});
|
||||
|
||||
@@ -21,9 +21,7 @@ namespace FEXCore::HLE {
|
||||
});
|
||||
|
||||
REGISTER_SYSCALL_IMPL(sigaltstack, [](FEXCore::Core::InternalThreadState *Thread, const stack_t *ss, stack_t *old_ss) -> uint64_t {
|
||||
// XXX: Pass through SignalDelegator
|
||||
uint64_t Result = ::sigaltstack(ss, old_ss);
|
||||
SYSCALL_ERRNO();
|
||||
return Thread->CTX->SignalDelegation.RegisterGuestSigAltStack(ss, old_ss);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user