| 82 | } |
| 83 | |
| 84 | static void duckgres_crash_handler(int sig, siginfo_t *info, void *uctx) { |
| 85 | // Keep this prefix in sync with crashhandler.Marker. |
| 86 | crash_write("\nduckgres: fatal native signal "); |
| 87 | crash_write(crash_signame(sig)); |
| 88 | crash_write(" pc "); |
| 89 | crash_write_hex(crash_pc(uctx)); |
| 90 | crash_write(" fault addr "); |
| 91 | crash_write_hex(info != NULL ? (uintptr_t)info->si_addr : 0); |
| 92 | crash_write(" - backtrace of crashed thread:\n"); |
| 93 | |
| 94 | void *bt[64]; |
| 95 | int n = backtrace(bt, 64); |
| 96 | backtrace_symbols_fd(bt, n, STDERR_FILENO); |
| 97 | |
| 98 | crash_write("duckgres: terminating with default signal disposition\n"); |
| 99 | |
| 100 | // Restore the default disposition and re-raise so the process dies with |
| 101 | // the original signal (and dumps core where enabled) instead of wedging. |
| 102 | struct sigaction dfl; |
| 103 | memset(&dfl, 0, sizeof(dfl)); |
| 104 | dfl.sa_handler = SIG_DFL; |
| 105 | sigemptyset(&dfl.sa_mask); |
| 106 | sigaction(sig, &dfl, NULL); |
| 107 | raise(sig); |
| 108 | // If the signal is blocked during handler execution, returning re-executes |
| 109 | // the faulting instruction and the (now default) action fires then. |
| 110 | } |
| 111 | |
| 112 | __attribute__((constructor)) static void duckgres_crashhandler_install(void) { |
| 113 | struct sigaction sa; |
nothing calls this directly
no test coverage detected