init_signals.cc revision 11235
1/* 2 * Copyright (c) 2012, 2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2000-2005 The Regents of The University of Michigan 15 * Copyright (c) 2008 The Hewlett-Packard Development Company 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Nathan Binkert 42 */ 43 44#include "sim/init_signals.hh" 45 46#include <sys/types.h> 47#include <unistd.h> 48 49#include <csignal> 50#include <iostream> 51#include <string> 52 53#include "base/atomicio.hh" 54#include "base/cprintf.hh" 55#include "sim/async.hh" 56#include "sim/backtrace.hh" 57#include "sim/core.hh" 58#include "sim/eventq.hh" 59 60using namespace std; 61 62// Use an separate stack for fatal signal handlers 63static uint8_t fatalSigStack[2 * SIGSTKSZ]; 64 65static bool 66setupAltStack() 67{ 68 stack_t stack; 69 stack.ss_sp = fatalSigStack; 70 stack.ss_size = sizeof(fatalSigStack); 71 stack.ss_flags = 0; 72 73 return sigaltstack(&stack, NULL) == 0; 74} 75 76static void 77installSignalHandler(int signal, void (*handler)(int sigtype), 78 int flags = SA_RESTART) 79{ 80 struct sigaction sa; 81 82 memset(&sa, 0, sizeof(sa)); 83 sigemptyset(&sa.sa_mask); 84 sa.sa_handler = handler; 85 sa.sa_flags = flags; 86 87 if (sigaction(signal, &sa, NULL) == -1) 88 panic("Failed to setup handler for signal %i\n", signal); 89} 90 91static void 92raiseFatalSignal(int signo) 93{ 94 // The signal handler should have been reset and unmasked (it was 95 // registered with SA_RESETHAND | SA_NODEFER), just raise the 96 // signal again to invoke the default handler. 97 pthread_kill(pthread_self(), signo); 98 99 // Something is really wrong if the process is alive at this 100 // point, manually try to exit it. 101 STATIC_ERR("Failed to execute default signal handler!\n"); 102 _exit(127); 103} 104 105/// Stats signal handler. 106void 107dumpStatsHandler(int sigtype) 108{ 109 async_event = true; 110 async_statdump = true; 111 /* Wake up some event queue to handle event */ 112 getEventQueue(0)->wakeup(); 113} 114 115void 116dumprstStatsHandler(int sigtype) 117{ 118 async_event = true; 119 async_statdump = true; 120 async_statreset = true; 121 /* Wake up some event queue to handle event */ 122 getEventQueue(0)->wakeup(); 123} 124 125/// Exit signal handler. 126void 127exitNowHandler(int sigtype) 128{ 129 async_event = true; 130 async_exit = true; 131 /* Wake up some event queue to handle event */ 132 getEventQueue(0)->wakeup(); 133} 134 135/// Abort signal handler. 136void 137abortHandler(int sigtype) 138{ 139 const EventQueue *const eq(curEventQueue()); 140 if (eq) { 141 ccprintf(cerr, "Program aborted at tick %llu\n", eq->getCurTick()); 142 } else { 143 STATIC_ERR("Program aborted\n\n"); 144 } 145 146 print_backtrace(); 147 raiseFatalSignal(sigtype); 148} 149 150/// Segmentation fault signal handler. 151static void 152segvHandler(int sigtype) 153{ 154 STATIC_ERR("gem5 has encountered a segmentation fault!\n\n"); 155 156 print_backtrace(); 157 raiseFatalSignal(SIGSEGV); 158} 159 160// Handle SIGIO 161static void 162ioHandler(int sigtype) 163{ 164 async_event = true; 165 async_io = true; 166 /* Wake up some event queue to handle event */ 167 getEventQueue(0)->wakeup(); 168} 169 170/* 171 * M5 can do several special things when various signals are sent. 172 * None are mandatory. 173 */ 174void 175initSignals() 176{ 177 // Floating point exceptions may happen on misspeculated paths, so 178 // ignore them 179 signal(SIGFPE, SIG_IGN); 180 181 // We use SIGTRAP sometimes for debugging 182 signal(SIGTRAP, SIG_IGN); 183 184 // Dump intermediate stats 185 installSignalHandler(SIGUSR1, dumpStatsHandler); 186 187 // Dump intermediate stats and reset them 188 installSignalHandler(SIGUSR2, dumprstStatsHandler); 189 190 // Exit cleanly on Interrupt (Ctrl-C) 191 installSignalHandler(SIGINT, exitNowHandler); 192 193 // Print the current cycle number and a backtrace on abort. Make 194 // sure the signal is unmasked and the handler reset when a signal 195 // is delivered to be able to invoke the default handler. 196 installSignalHandler(SIGABRT, abortHandler, SA_RESETHAND | SA_NODEFER); 197 198 // Setup a SIGSEGV handler with a private stack 199 if (setupAltStack()) { 200 installSignalHandler(SIGSEGV, segvHandler, 201 SA_RESETHAND | SA_NODEFER | SA_ONSTACK); 202 } else { 203 warn("Failed to setup stack for SIGSEGV handler, " 204 "using default signal handler.\n"); 205 } 206 207 // Install a SIGIO handler to handle asynchronous file IO. See the 208 // PollQueue class. 209 installSignalHandler(SIGIO, ioHandler); 210} 211 212