MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add crash handler

+158
+6
include/crash.h
··· 1 + #ifndef ANT_CRASH_H 2 + #define ANT_CRASH_H 3 + 4 + void ant_crash_init(void); 5 + 6 + #endif
+149
src/crash.c
··· 1 + #include <compat.h> // IWYU pragma: keep 2 + #include "crash.h" 3 + 4 + #include <stdio.h> 5 + #include <stdint.h> 6 + #include <stdlib.h> 7 + #include <string.h> 8 + #include <unistd.h> 9 + 10 + #ifndef _WIN32 11 + #include <signal.h> 12 + 13 + #define ANT_CRASH_ALT_STACK_SIZE (64 * 1024) 14 + 15 + #if defined(__APPLE__) || defined(__linux__) || defined(__GLIBC__) 16 + #define ANT_CRASH_HAVE_EXECINFO 1 17 + #include <execinfo.h> 18 + #endif 19 + 20 + static void as_write(int fd, const char *s) { 21 + size_t len = 0; 22 + while (s[len]) len++; 23 + ssize_t _ = write(fd, s, len); 24 + (void)_; 25 + } 26 + 27 + static void as_write_uint(int fd, unsigned long v) { 28 + char buf[32]; 29 + int i = (int)sizeof(buf); 30 + buf[--i] = '\0'; 31 + if (v == 0) buf[--i] = '0'; 32 + while (v && i > 0) { 33 + buf[--i] = (char)('0' + (v % 10)); 34 + v /= 10; 35 + } 36 + as_write(fd, &buf[i]); 37 + } 38 + 39 + static int install_altstack(void) { 40 + #ifdef SA_ONSTACK 41 + static void *stack_mem; 42 + if (stack_mem) return 1; 43 + 44 + stack_mem = malloc(ANT_CRASH_ALT_STACK_SIZE); 45 + if (!stack_mem) return 0; 46 + 47 + stack_t ss; 48 + memset(&ss, 0, sizeof(ss)); 49 + ss.ss_sp = stack_mem; 50 + ss.ss_size = ANT_CRASH_ALT_STACK_SIZE; 51 + ss.ss_flags = 0; 52 + 53 + if (sigaltstack(&ss, NULL) == 0) return 1; 54 + 55 + free(stack_mem); 56 + stack_mem = NULL; 57 + #endif 58 + return 0; 59 + } 60 + 61 + static const char *signal_name(int sig) { 62 + switch (sig) { 63 + case SIGSEGV: return "SIGSEGV (invalid memory access)"; 64 + case SIGBUS: return "SIGBUS (bus error)"; 65 + case SIGFPE: return "SIGFPE (arithmetic exception)"; 66 + case SIGILL: return "SIGILL (illegal instruction)"; 67 + case SIGABRT: return "SIGABRT (abort)"; 68 + default: return "fatal signal"; 69 + }} 70 + 71 + static void crash_handler(int sig, siginfo_t *info, void *ucontext) { 72 + struct sigaction dfl; 73 + memset(&dfl, 0, sizeof(dfl)); 74 + 75 + dfl.sa_handler = SIG_DFL; 76 + sigemptyset(&dfl.sa_mask); 77 + sigaction(sig, &dfl, NULL); 78 + 79 + int fd = STDERR_FILENO; 80 + as_write(fd, "\n=== ant crashed: "); 81 + as_write(fd, signal_name(sig)); 82 + as_write(fd, " (signal "); 83 + as_write_uint(fd, (unsigned long)sig); 84 + as_write(fd, ") ===\n"); 85 + 86 + if (info) { 87 + as_write(fd, " fault address: 0x"); 88 + char hex[2 + sizeof(void *) * 2 + 1]; 89 + int hi = (int)sizeof(hex); 90 + 91 + hex[--hi] = '\0'; 92 + uintptr_t addr = (uintptr_t)info->si_addr; 93 + 94 + if (addr == 0) hex[--hi] = '0'; 95 + else while (addr && hi > 0) { 96 + unsigned d = (unsigned)(addr & 0xF); 97 + hex[--hi] = (char)(d < 10 ? '0' + d : 'a' + d - 10); 98 + addr >>= 4; 99 + } 100 + 101 + as_write(fd, &hex[hi]); 102 + as_write(fd, "\n"); 103 + } 104 + 105 + as_write(fd, " ant version: " ANT_VERSION "\n"); 106 + as_write(fd, " pid: "); 107 + as_write_uint(fd, (unsigned long)getpid()); 108 + as_write(fd, "\n\nNative backtrace:\n"); 109 + 110 + #ifdef ANT_CRASH_HAVE_EXECINFO 111 + void *frames[64]; 112 + int n = backtrace(frames, (int)(sizeof(frames) / sizeof(frames[0]))); 113 + int skip = n > 2 ? 2 : 0; 114 + if (skip) as_write(fd, " (omitted crash_handler and signal trampoline frames)\n"); 115 + backtrace_symbols_fd(frames + skip, n - skip, fd); 116 + #else 117 + as_write(fd, " (no execinfo support on this platform)\n"); 118 + #endif 119 + 120 + as_write(fd, 121 + "\nPlease report this at https://github.com/themackabu/ant/issues\n" 122 + "Include the backtrace above and a minimal reproducer if possible.\n\n"); 123 + 124 + raise(sig); 125 + } 126 + 127 + void ant_crash_init(void) { 128 + struct sigaction sa; 129 + memset(&sa, 0, sizeof(sa)); 130 + sa.sa_sigaction = crash_handler; 131 + sa.sa_flags = SA_SIGINFO | SA_RESETHAND; 132 + #ifdef SA_ONSTACK 133 + if (install_altstack()) sa.sa_flags |= SA_ONSTACK; 134 + #endif 135 + sigemptyset(&sa.sa_mask); 136 + 137 + static const int sigs[] = { SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGABRT }; 138 + for (size_t i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++) { 139 + sigaction(sigs[i], &sa, NULL); 140 + } 141 + } 142 + 143 + #else // _WIN32 144 + 145 + void ant_crash_init(void) { 146 + // TODO: SetUnhandledExceptionFilter + StackWalk64 / dbghelp 147 + } 148 + 149 + #endif
+3
src/main.c
··· 10 10 11 11 #include "ant.h" 12 12 #include "gc.h" 13 + #include "crash.h" 13 14 #include "repl.h" 14 15 #include "debug.h" 15 16 #include "utils.h" ··· 378 379 } 379 380 380 381 int main(int argc, char *argv[]) { 382 + if (!getenv("ANT_NO_CRASH_HANDLER")) ant_crash_init(); 383 + 381 384 setup_console_colors(); 382 385 parse_ant_debug_flags(); 383 386