diff options
Diffstat (limited to 'ARMeilleure/Signal/UnixSignalHandlerRegistration.cs')
-rw-r--r-- | ARMeilleure/Signal/UnixSignalHandlerRegistration.cs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs b/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs new file mode 100644 index 00000000..9e87749e --- /dev/null +++ b/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs @@ -0,0 +1,57 @@ +using Mono.Unix.Native; +using System; +using System.Runtime.InteropServices; + +namespace ARMeilleure.Signal +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + unsafe struct SigSet + { + fixed long sa_mask[16]; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SigAction + { + public IntPtr sa_handler; + public SigSet sa_mask; + public int sa_flags; + public IntPtr sa_restorer; + } + + static class UnixSignalHandlerRegistration + { + private const int SA_SIGINFO = 0x00000004; + + [DllImport("libc", SetLastError = true)] + private static extern int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction); + + [DllImport("libc", SetLastError = true)] + private static extern int sigemptyset(ref SigSet set); + + public static SigAction RegisterExceptionHandler(IntPtr action) + { + SigAction sig = new SigAction + { + sa_handler = action, + sa_flags = SA_SIGINFO + }; + + sigemptyset(ref sig.sa_mask); + + int result = sigaction((int)Signum.SIGSEGV, ref sig, out SigAction old); + + if (result != 0) + { + throw new InvalidOperationException($"Could not register sigaction. Error: {result}"); + } + + return old; + } + + public static bool RestoreExceptionHandler(SigAction oldAction) + { + return sigaction((int)Signum.SIGSEGV, ref oldAction, out SigAction _) == 0; + } + } +} |