diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2024-01-18 14:08:40 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-18 14:08:40 -0300 |
| commit | 2dbbc9bc05998baa94d7b1953d9e0ffc7f1651f8 (patch) | |
| tree | 5a3bf00a55f4c1a92b681119aef6dd68315b60e5 /src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs | |
| parent | 72634c80f408fd6cf6602c8c6729643e9ea1ffe3 (diff) | |
Move most of signal handling to Ryujinx.Cpu project (#6128)
* Move most of signal handling to Ryujinx.Cpu project
* Format whitespace
* Remove unused member
* Format whitespace
* This does not need to be public anymore
Diffstat (limited to 'src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs')
| -rw-r--r-- | src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs b/src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs new file mode 100644 index 00000000..e88a6c0f --- /dev/null +++ b/src/Ryujinx.Cpu/Signal/UnixSignalHandlerRegistration.cs @@ -0,0 +1,83 @@ +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Cpu.Signal +{ + static partial class UnixSignalHandlerRegistration + { + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public unsafe struct SigSet + { + fixed long sa_mask[16]; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SigAction + { + public IntPtr sa_handler; + public SigSet sa_mask; + public int sa_flags; + public IntPtr sa_restorer; + } + + private const int SIGSEGV = 11; + private const int SIGBUS = 10; + private const int SA_SIGINFO = 0x00000004; + + [LibraryImport("libc", SetLastError = true)] + private static partial int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction); + + [LibraryImport("libc", SetLastError = true)] + private static partial int sigaction(int signum, IntPtr sigAction, out SigAction oldAction); + + [LibraryImport("libc", SetLastError = true)] + private static partial int sigemptyset(ref SigSet set); + + public static SigAction GetSegfaultExceptionHandler() + { + int result = sigaction(SIGSEGV, IntPtr.Zero, out SigAction old); + + if (result != 0) + { + throw new InvalidOperationException($"Could not get SIGSEGV sigaction. Error: {result}"); + } + + return old; + } + + public static SigAction RegisterExceptionHandler(IntPtr action) + { + SigAction sig = new() + { + sa_handler = action, + sa_flags = SA_SIGINFO, + }; + + sigemptyset(ref sig.sa_mask); + + int result = sigaction(SIGSEGV, ref sig, out SigAction old); + + if (result != 0) + { + throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}"); + } + + if (OperatingSystem.IsMacOS()) + { + result = sigaction(SIGBUS, ref sig, out _); + + if (result != 0) + { + throw new InvalidOperationException($"Could not register SIGBUS sigaction. Error: {result}"); + } + } + + return old; + } + + public static bool RestoreExceptionHandler(SigAction oldAction) + { + return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0); + } + } +} |
