// where should this go... extern "C" void abort() { static void (*libc_abort)() = (void (*)())dlsym(RTLD_NEXT, "abort"); // In case something calls abort down the line: static bool recursive = false; if (!recursive) { recursive = true; fprintf(stderr, "Someone called abort!\n"); // If we call abort(), things may be seriously wrong. Set an alarm() to // try to handle cases that we would just hang. // (Ex if we abort() from a static constructor, and _printStackTrace uses // that object, _printStackTrace will hang waiting for the first construction // to finish.) alarm(1); try { _printStacktrace(); } catch (ExcInfo) { fprintf(stderr, "error printing stack trace during abort()"); } // Cancel the alarm. // This is helpful for when running in a debugger, since the debugger will catch the // abort and let you investigate, but the alarm will still come back to kill the program. alarm(0); } libc_abort(); __builtin_unreachable(); }
// where should this go... extern "C" void abort() { static void (*libc_abort)() = (void (*)())dlsym(RTLD_NEXT, "abort"); // In case something calls abort down the line: static bool recursive = false; if (!recursive) { recursive = true; fprintf(stderr, "Someone called abort!\n"); _printStacktrace(); } libc_abort(); __builtin_unreachable(); }
extern "C" void exit(int code) { static void (*libc_exit)(int) = (void (*)(int))dlsym(RTLD_NEXT, "exit"); if (code == 0) { libc_exit(0); __builtin_unreachable(); } fprintf(stderr, "Someone called exit with code=%d!\n", code); // In case something calls exit down the line: static bool recursive = false; if (!recursive) { recursive = true; _printStacktrace(); } libc_exit(code); __builtin_unreachable(); }
static void handle_sigusr1(int signum) { assert(signum == SIGUSR1); fprintf(stderr, "SIGUSR1, printing stack trace\n"); _printStacktrace(); }