runtime_unix.c raw
1 //go:build none
2
3 // This file is included on Darwin and Linux (despite the //go:build line above).
4
5 #define _GNU_SOURCE
6 #define _XOPEN_SOURCE
7 #include <signal.h>
8 #include <unistd.h>
9 #include <stdint.h>
10 #include <ucontext.h>
11 #include <string.h>
12
13 void moxie_handle_fatal_signal(int sig, uintptr_t addr);
14
15 static void signal_handler(int sig, siginfo_t *info, void *context) {
16 ucontext_t* uctx = context;
17 uintptr_t addr = 0;
18 #if __APPLE__
19 #if __arm64__
20 addr = uctx->uc_mcontext->__ss.__pc;
21 #elif __x86_64__
22 addr = uctx->uc_mcontext->__ss.__rip;
23 #else
24 #error unknown architecture
25 #endif
26 #elif __linux__
27 // Note: this can probably be simplified using the MC_PC macro in musl,
28 // but this works for now.
29 #if __arm__
30 addr = uctx->uc_mcontext.arm_pc;
31 #elif __i386__
32 addr = uctx->uc_mcontext.gregs[REG_EIP];
33 #elif __x86_64__
34 addr = uctx->uc_mcontext.gregs[REG_RIP];
35 #else // aarch64, mips, maybe others
36 addr = uctx->uc_mcontext.pc;
37 #endif
38 #else
39 #error unknown platform
40 #endif
41 moxie_handle_fatal_signal(sig, addr);
42 }
43
44 void moxie_register_fatal_signals(void) {
45 // Ignore SIGPIPE — network servers must not die on write-to-closed-socket.
46 // Go's runtime does this; moxie must too.
47 signal(SIGPIPE, SIG_IGN);
48
49 struct sigaction act = { 0 };
50 // SA_SIGINFO: we want the 2 extra parameters
51 // SA_RESETHAND: only catch the signal once (the handler will re-raise the signal)
52 act.sa_flags = SA_SIGINFO | SA_RESETHAND;
53 act.sa_sigaction = &signal_handler;
54
55 // Register the signal handler for common issues. There are more signals,
56 // which can be added if needed.
57 sigaction(SIGBUS, &act, NULL);
58 sigaction(SIGILL, &act, NULL);
59 sigaction(SIGSEGV, &act, NULL);
60 }
61