X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsim%2Finit_signals.cc;h=501f4eb9d133e345797fc26d33f33a132c145a73;hb=200281b08ca21f0d2678e23063f088960d3c0819;hp=7efbaea616e1c0fc9612328e950e5504d7df77d0;hpb=8e74d5484f0b207c10a585ea3270430f398cfa8a;p=gem5.git diff --git a/src/sim/init_signals.cc b/src/sim/init_signals.cc index 7efbaea61..501f4eb9d 100644 --- a/src/sim/init_signals.cc +++ b/src/sim/init_signals.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 ARM Limited + * Copyright (c) 2012, 2015 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -41,18 +41,77 @@ * Authors: Nathan Binkert */ +#include "sim/init_signals.hh" + +#include +#include + #include #include #include +#if defined(__FreeBSD__) +#include + +#endif + +#include "base/atomicio.hh" #include "base/cprintf.hh" +#include "base/logging.hh" #include "sim/async.hh" +#include "sim/backtrace.hh" #include "sim/core.hh" #include "sim/eventq.hh" -#include "sim/init_signals.hh" using namespace std; +// Use an separate stack for fatal signal handlers +static uint8_t fatalSigStack[2 * SIGSTKSZ]; + +static bool +setupAltStack() +{ + stack_t stack; +#if defined(__FreeBSD__) && (__FreeBSD_version < 1100097) + stack.ss_sp = (char *)fatalSigStack; +#else + stack.ss_sp = fatalSigStack; +#endif + stack.ss_size = sizeof(fatalSigStack); + stack.ss_flags = 0; + + return sigaltstack(&stack, NULL) == 0; +} + +static void +installSignalHandler(int signal, void (*handler)(int sigtype), + int flags = SA_RESTART) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = handler; + sa.sa_flags = flags; + + if (sigaction(signal, &sa, NULL) == -1) + panic("Failed to setup handler for signal %i\n", signal); +} + +static void +raiseFatalSignal(int signo) +{ + // The signal handler should have been reset and unmasked (it was + // registered with SA_RESETHAND | SA_NODEFER), just raise the + // signal again to invoke the default handler. + pthread_kill(pthread_self(), signo); + + // Something is really wrong if the process is alive at this + // point, manually try to exit it. + STATIC_ERR("Failed to execute default signal handler!\n"); + _exit(127); +} + /// Stats signal handler. void dumpStatsHandler(int sigtype) @@ -87,7 +146,25 @@ exitNowHandler(int sigtype) void abortHandler(int sigtype) { - ccprintf(cerr, "Program aborted at tick %llu\n", curTick()); + const EventQueue *const eq(curEventQueue()); + if (eq) { + ccprintf(cerr, "Program aborted at tick %llu\n", eq->getCurTick()); + } else { + STATIC_ERR("Program aborted\n\n"); + } + + print_backtrace(); + raiseFatalSignal(sigtype); +} + +/// Segmentation fault signal handler. +static void +segvHandler(int sigtype) +{ + STATIC_ERR("gem5 has encountered a segmentation fault!\n\n"); + + print_backtrace(); + raiseFatalSignal(SIGSEGV); } // Handle SIGIO @@ -100,20 +177,6 @@ ioHandler(int sigtype) getEventQueue(0)->wakeup(); } -static void -installSignalHandler(int signal, void (*handler)(int sigtype)) -{ - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_handler = handler; - sa.sa_flags = SA_RESTART; - - if (sigaction(signal, &sa, NULL) == -1) - panic("Failed to setup handler for signal %i\n", signal); -} - /* * M5 can do several special things when various signals are sent. * None are mandatory. @@ -125,9 +188,6 @@ initSignals() // ignore them signal(SIGFPE, SIG_IGN); - // We use SIGTRAP sometimes for debugging - signal(SIGTRAP, SIG_IGN); - // Dump intermediate stats installSignalHandler(SIGUSR1, dumpStatsHandler); @@ -137,8 +197,19 @@ initSignals() // Exit cleanly on Interrupt (Ctrl-C) installSignalHandler(SIGINT, exitNowHandler); - // Print out cycle number on abort - installSignalHandler(SIGABRT, abortHandler); + // Print the current cycle number and a backtrace on abort. Make + // sure the signal is unmasked and the handler reset when a signal + // is delivered to be able to invoke the default handler. + installSignalHandler(SIGABRT, abortHandler, SA_RESETHAND | SA_NODEFER); + + // Setup a SIGSEGV handler with a private stack + if (setupAltStack()) { + installSignalHandler(SIGSEGV, segvHandler, + SA_RESETHAND | SA_NODEFER | SA_ONSTACK); + } else { + warn("Failed to setup stack for SIGSEGV handler, " + "using default signal handler.\n"); + } // Install a SIGIO handler to handle asynchronous file IO. See the // PollQueue class.