Disable the crash reporter when running lit tests.
[oota-llvm.git] / lib / Support / Unix / Signals.inc
1 //===- Signals.cpp - Generic Unix Signals Implementation -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines some helpful functions for dealing with the possibility of
11 // Unix signals occurring while your program is running.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "Unix.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Support/Mutex.h"
18 #include <vector>
19 #include <algorithm>
20 #if HAVE_EXECINFO_H
21 # include <execinfo.h>         // For backtrace().
22 #endif
23 #if HAVE_SIGNAL_H
24 #include <signal.h>
25 #endif
26 #if HAVE_SYS_STAT_H
27 #include <sys/stat.h>
28 #endif
29 #if HAVE_DLFCN_H && __GNUG__
30 #include <dlfcn.h>
31 #include <cxxabi.h>
32 #endif
33 #if HAVE_MACH_MACH_H
34 #include <mach/mach.h>
35 #endif
36
37 using namespace llvm;
38
39 static RETSIGTYPE SignalHandler(int Sig);  // defined below.
40
41 static SmartMutex<true> SignalsMutex;
42
43 /// InterruptFunction - The function to call if ctrl-c is pressed.
44 static void (*InterruptFunction)() = 0;
45
46 static std::vector<sys::Path> FilesToRemove;
47 static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun;
48
49 // IntSigs - Signals that may interrupt the program at any time.
50 static const int IntSigs[] = {
51   SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
52 };
53 static const int *const IntSigsEnd =
54   IntSigs + sizeof(IntSigs) / sizeof(IntSigs[0]);
55
56 // KillSigs - Signals that are synchronous with the program that will cause it
57 // to die.
58 static const int KillSigs[] = {
59   SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV
60 #ifdef SIGSYS
61   , SIGSYS
62 #endif
63 #ifdef SIGXCPU
64   , SIGXCPU
65 #endif
66 #ifdef SIGXFSZ
67   , SIGXFSZ
68 #endif
69 #ifdef SIGEMT
70   , SIGEMT
71 #endif
72 };
73 static const int *const KillSigsEnd =
74   KillSigs + sizeof(KillSigs) / sizeof(KillSigs[0]);
75
76 static unsigned NumRegisteredSignals = 0;
77 static struct {
78   struct sigaction SA;
79   int SigNo;
80 } RegisteredSignalInfo[(sizeof(IntSigs)+sizeof(KillSigs))/sizeof(KillSigs[0])];
81
82
83 static void RegisterHandler(int Signal) {
84   assert(NumRegisteredSignals <
85          sizeof(RegisteredSignalInfo)/sizeof(RegisteredSignalInfo[0]) &&
86          "Out of space for signal handlers!");
87
88   struct sigaction NewHandler;
89
90   NewHandler.sa_handler = SignalHandler;
91   NewHandler.sa_flags = SA_NODEFER|SA_RESETHAND;
92   sigemptyset(&NewHandler.sa_mask);
93
94   // Install the new handler, save the old one in RegisteredSignalInfo.
95   sigaction(Signal, &NewHandler,
96             &RegisteredSignalInfo[NumRegisteredSignals].SA);
97   RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal;
98   ++NumRegisteredSignals;
99 }
100
101 static void RegisterHandlers() {
102   // If the handlers are already registered, we're done.
103   if (NumRegisteredSignals != 0) return;
104
105   std::for_each(IntSigs, IntSigsEnd, RegisterHandler);
106   std::for_each(KillSigs, KillSigsEnd, RegisterHandler);
107 }
108
109 static void UnregisterHandlers() {
110   // Restore all of the signal handlers to how they were before we showed up.
111   for (unsigned i = 0, e = NumRegisteredSignals; i != e; ++i)
112     sigaction(RegisteredSignalInfo[i].SigNo,
113               &RegisteredSignalInfo[i].SA, 0);
114   NumRegisteredSignals = 0;
115 }
116
117
118 /// RemoveFilesToRemove - Process the FilesToRemove list. This function
119 /// should be called with the SignalsMutex lock held.
120 static void RemoveFilesToRemove() {
121   while (!FilesToRemove.empty()) {
122     FilesToRemove.back().eraseFromDisk(true);
123     FilesToRemove.pop_back();
124   }
125 }
126
127 // SignalHandler - The signal handler that runs.
128 static RETSIGTYPE SignalHandler(int Sig) {
129   // Restore the signal behavior to default, so that the program actually
130   // crashes when we return and the signal reissues.  This also ensures that if
131   // we crash in our signal handler that the program will terminate immediately
132   // instead of recursing in the signal handler.
133   UnregisterHandlers();
134
135   // Unmask all potentially blocked kill signals.
136   sigset_t SigMask;
137   sigfillset(&SigMask);
138   sigprocmask(SIG_UNBLOCK, &SigMask, 0);
139
140   SignalsMutex.acquire();
141   RemoveFilesToRemove();
142
143   if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) {
144     if (InterruptFunction) {
145       void (*IF)() = InterruptFunction;
146       SignalsMutex.release();
147       InterruptFunction = 0;
148       IF();        // run the interrupt function.
149       return;
150     }
151
152     SignalsMutex.release();
153     raise(Sig);   // Execute the default handler.
154     return;
155   }
156
157   SignalsMutex.release();
158
159   // Otherwise if it is a fault (like SEGV) run any handler.
160   for (unsigned i = 0, e = CallBacksToRun.size(); i != e; ++i)
161     CallBacksToRun[i].first(CallBacksToRun[i].second);
162 }
163
164 void llvm::sys::RunInterruptHandlers() {
165   SignalsMutex.acquire();
166   RemoveFilesToRemove();
167   SignalsMutex.release();
168 }
169
170 void llvm::sys::SetInterruptFunction(void (*IF)()) {
171   SignalsMutex.acquire();
172   InterruptFunction = IF;
173   SignalsMutex.release();
174   RegisterHandlers();
175 }
176
177 // RemoveFileOnSignal - The public API
178 bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename,
179                                    std::string* ErrMsg) {
180   SignalsMutex.acquire();
181   FilesToRemove.push_back(Filename);
182
183   SignalsMutex.release();
184
185   RegisterHandlers();
186   return false;
187 }
188
189 // DontRemoveFileOnSignal - The public API
190 void llvm::sys::DontRemoveFileOnSignal(const sys::Path &Filename) {
191   SignalsMutex.acquire();
192   std::vector<sys::Path>::reverse_iterator I =
193     std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename);
194   if (I != FilesToRemove.rend())
195     FilesToRemove.erase(I.base()-1);
196   SignalsMutex.release();
197 }
198
199 /// AddSignalHandler - Add a function to be called when a signal is delivered
200 /// to the process.  The handler can have a cookie passed to it to identify
201 /// what instance of the handler it is.
202 void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
203   CallBacksToRun.push_back(std::make_pair(FnPtr, Cookie));
204   RegisterHandlers();
205 }
206
207
208 // PrintStackTrace - In the case of a program crash or fault, print out a stack
209 // trace so that the user has an indication of why and where we died.
210 //
211 // On glibc systems we have the 'backtrace' function, which works nicely, but
212 // doesn't demangle symbols.
213 static void PrintStackTrace(void *) {
214 #ifdef HAVE_BACKTRACE
215   static void* StackTrace[256];
216   // Use backtrace() to output a backtrace on Linux systems with glibc.
217   int depth = backtrace(StackTrace,
218                         static_cast<int>(array_lengthof(StackTrace)));
219 #if HAVE_DLFCN_H && __GNUG__
220   int width = 0;
221   for (int i = 0; i < depth; ++i) {
222     Dl_info dlinfo;
223     dladdr(StackTrace[i], &dlinfo);
224     const char* name = strrchr(dlinfo.dli_fname, '/');
225
226     int nwidth;
227     if (name == NULL) nwidth = strlen(dlinfo.dli_fname);
228     else              nwidth = strlen(name) - 1;
229
230     if (nwidth > width) width = nwidth;
231   }
232
233   for (int i = 0; i < depth; ++i) {
234     Dl_info dlinfo;
235     dladdr(StackTrace[i], &dlinfo);
236
237     fprintf(stderr, "%-2d", i);
238
239     const char* name = strrchr(dlinfo.dli_fname, '/');
240     if (name == NULL) fprintf(stderr, " %-*s", width, dlinfo.dli_fname);
241     else              fprintf(stderr, " %-*s", width, name+1);
242
243     fprintf(stderr, " %#0*lx",
244             (int)(sizeof(void*) * 2) + 2, (unsigned long)StackTrace[i]);
245
246     if (dlinfo.dli_sname != NULL) {
247       int res;
248       fputc(' ', stderr);
249       char* d = abi::__cxa_demangle(dlinfo.dli_sname, NULL, NULL, &res);
250       if (d == NULL) fputs(dlinfo.dli_sname, stderr);
251       else           fputs(d, stderr);
252       free(d);
253
254       fprintf(stderr, " + %tu",(char*)StackTrace[i]-(char*)dlinfo.dli_saddr);
255     }
256     fputc('\n', stderr);
257   }
258 #else
259   backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
260 #endif
261 #endif
262 }
263
264 /// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
265 /// SIGSEGV) is delivered to the process, print a stack trace and then exit.
266 void llvm::sys::PrintStackTraceOnErrorSignal() {
267   AddSignalHandler(PrintStackTrace, 0);
268
269 #if defined(__APPLE__)
270   // Environment variable to disable any kind of crash dialog.
271   if (getenv("LLVM_DISABLE_CRASH_REPORT")) {
272     mach_port_t self = mach_task_self();
273
274     exception_mask_t mask = EXC_MASK_CRASH;
275
276     kern_return_t ret = task_set_exception_ports(self, 
277                              mask,
278                              NULL,
279                              EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, 
280                              NULL);
281     (void)ret;
282   }
283 #endif
284 }
285
286
287 /***/
288
289 // On Darwin, raise sends a signal to the main thread instead of the current
290 // thread. This has the unfortunate effect that assert() and abort() will end up
291 // bypassing our crash recovery attempts. We work around this for anything in
292 // the same linkage unit by just defining our own versions of the assert handler
293 // and abort.
294
295 #ifdef __APPLE__
296
297 #include <signal.h>
298 #include <pthread.h>
299
300 int raise(int sig) {
301   return pthread_kill(pthread_self(), sig);
302 }
303
304 void __assert_rtn(const char *func,
305                   const char *file,
306                   int line,
307                   const char *expr) {
308   if (func)
309     fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n",
310             expr, func, file, line);
311   else
312     fprintf(stderr, "Assertion failed: (%s), file %s, line %d.\n",
313             expr, file, line);
314   abort();
315 }
316
317 void abort() {
318   raise(SIGABRT);
319   usleep(1000);
320   __builtin_trap();
321 }
322
323 #endif