X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FUnix%2FSignals.inc;h=bfe2a3a380edcb7efe4c38e5b88d41894105a9fb;hb=82b39321e5bb87e999678e85eb5973919524b104;hp=9291b6173571043bec009e8e159853e12db89715;hpb=ee3948fdbed2737242e2c8d0a945fd075940f2f7;p=oota-llvm.git diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index 9291b617357..bfe2a3a380e 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -14,6 +14,7 @@ #include "Unix.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Format.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/ManagedStatic.h" @@ -111,6 +112,12 @@ static void RegisterHandler(int Signal) { } static void RegisterHandlers() { + // We need to dereference the signals mutex during handler registration so + // that we force its construction. This is to prevent the first use being + // during handling an actual signal because you can't safely call new in a + // signal handler. + *SignalsMutex; + // If the handlers are already registered, we're done. if (NumRegisteredSignals != 0) return; @@ -132,6 +139,11 @@ static void UnregisterHandlers() { /// NB: This must be an async signal safe function. It cannot allocate or free /// memory, even in debug builds. static void RemoveFilesToRemove() { + // Avoid constructing ManagedStatic in the signal handler. + // If FilesToRemove is not constructed, there are no files to remove. + if (!FilesToRemove.isConstructed()) + return; + // We avoid iterators in case of debug iterators that allocate or release // memory. std::vector& FilesToRemoveRef = *FilesToRemove; @@ -193,10 +205,11 @@ static RETSIGTYPE SignalHandler(int Sig) { } // Otherwise if it is a fault (like SEGV) run any handler. - std::vector>& CallBacksToRunRef = - *CallBacksToRun; - for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) - CallBacksToRunRef[i].first(CallBacksToRunRef[i].second); + if (CallBacksToRun.isConstructed()) { + auto &CallBacksToRunRef = *CallBacksToRun; + for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) + CallBacksToRunRef[i].first(CallBacksToRunRef[i].second); + } #ifdef __s390__ // On S/390, certain signals are delivered with PSW Address pointing to @@ -272,7 +285,10 @@ void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { RegisterHandlers(); } -#if HAVE_LINK_H +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + +#if HAVE_LINK_H && (defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__NetBSD__)) struct DlIteratePhdrData { void **StackTrace; int depth; @@ -287,7 +303,7 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { const char *name = data->first ? data->main_exec_name : info->dlpi_name; data->first = false; for (int i = 0; i < info->dlpi_phnum; i++) { - const ElfW(Phdr) *phdr = &info->dlpi_phdr[i]; + const auto *phdr = &info->dlpi_phdr[i]; if (phdr->p_type != PT_LOAD) continue; intptr_t beg = info->dlpi_addr + phdr->p_vaddr; @@ -321,13 +337,16 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth, } #endif -static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) { +static bool printSymbolizedStackTrace(void **StackTrace, int Depth, + llvm::raw_ostream &OS) { // FIXME: Subtract necessary number from StackTrace entries to turn return addresses // into actual instruction addresses. // Use llvm-symbolizer tool to symbolize the stack traces. - std::string LLVMSymbolizerPath = sys::FindProgramByName("llvm-symbolizer"); - if (LLVMSymbolizerPath.empty()) + ErrorOr LLVMSymbolizerPathOrErr = + sys::findProgramByName("llvm-symbolizer"); + if (!LLVMSymbolizerPathOrErr) return false; + const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; // We don't know argv0 or the address of main() at this point, but try // to guess it anyway (it's possible on some platforms). std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); @@ -346,13 +365,6 @@ static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) { sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); FileRemover InputRemover(InputFile.c_str()); FileRemover OutputRemover(OutputFile.c_str()); - std::vector Redirects(3, nullptr); - StringRef InputFileStr(InputFile); - StringRef OutputFileStr(OutputFile); - StringRef StderrFileStr; - Redirects[0] = &InputFileStr; - Redirects[1] = &OutputFileStr; - Redirects[2] = &StderrFileStr; { raw_fd_ostream Input(InputFD, true); @@ -362,14 +374,20 @@ static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) { } } - const char *args[] = {"llvm-symbolizer", nullptr}; + StringRef InputFileStr(InputFile); + StringRef OutputFileStr(OutputFile); + StringRef StderrFileStr; + const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr, + &StderrFileStr}; + const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", + "--demangle", nullptr}; int RunResult = - sys::ExecuteAndWait(LLVMSymbolizerPath, args, nullptr, Redirects.data()); + sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); if (RunResult != 0) return false; auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); - if (std::error_code Err = OutputBuf.getError()) + if (!OutputBuf) return false; StringRef Output = OutputBuf.get()->getBuffer(); SmallVector Lines; @@ -378,41 +396,46 @@ static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) { int frame_no = 0; for (int i = 0; i < Depth; i++) { if (!Modules[i]) { - fprintf(FD, "#%d %p\n", frame_no++, StackTrace[i]); + OS << format("#%d %p\n", frame_no++, StackTrace[i]); continue; } // Read pairs of lines (function name and file/line info) until we // encounter empty line. for (;;) { + if (CurLine == Lines.end()) + return false; StringRef FunctionName = *CurLine++; if (FunctionName.empty()) break; - fprintf(FD, "#%d %p ", frame_no++, StackTrace[i]); + OS << format("#%d %p ", frame_no++, StackTrace[i]); if (!FunctionName.startswith("??")) - fprintf(FD, "%s ", FunctionName.str().c_str()); + OS << format("%s ", FunctionName.str().c_str()); + if (CurLine == Lines.end()) + return false; StringRef FileLineInfo = *CurLine++; if (!FileLineInfo.startswith("??")) - fprintf(FD, "%s", FileLineInfo.str().c_str()); + OS << format("%s", FileLineInfo.str().c_str()); else - fprintf(FD, "(%s+%p)", Modules[i], (void *)Offsets[i]); - fprintf(FD, "\n"); + OS << format("(%s+%p)", Modules[i], (void *)Offsets[i]); + OS << "\n"; } } return true; } +#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) // PrintStackTrace - In the case of a program crash or fault, print out a stack // trace so that the user has an indication of why and where we died. // // On glibc systems we have the 'backtrace' function, which works nicely, but // doesn't demangle symbols. -void llvm::sys::PrintStackTrace(FILE *FD) { +void llvm::sys::PrintStackTrace(raw_ostream &OS) { #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) static void* StackTrace[256]; // Use backtrace() to output a backtrace on Linux systems with glibc. int depth = backtrace(StackTrace, static_cast(array_lengthof(StackTrace))); - if (printSymbolizedStackTrace(StackTrace, depth, FD)) + if (printSymbolizedStackTrace(StackTrace, depth, OS)) return; #if HAVE_DLFCN_H && __GNUG__ int width = 0; @@ -432,34 +455,34 @@ void llvm::sys::PrintStackTrace(FILE *FD) { Dl_info dlinfo; dladdr(StackTrace[i], &dlinfo); - fprintf(FD, "%-2d", i); + OS << format("%-2d", i); const char* name = strrchr(dlinfo.dli_fname, '/'); - if (!name) fprintf(FD, " %-*s", width, dlinfo.dli_fname); - else fprintf(FD, " %-*s", width, name+1); + if (!name) OS << format(" %-*s", width, dlinfo.dli_fname); + else OS << format(" %-*s", width, name+1); - fprintf(FD, " %#0*lx", - (int)(sizeof(void*) * 2) + 2, (unsigned long)StackTrace[i]); + OS << format(" %#0*lx", (int)(sizeof(void*) * 2) + 2, + (unsigned long)StackTrace[i]); if (dlinfo.dli_sname != nullptr) { - fputc(' ', FD); + OS << ' '; # if HAVE_CXXABI_H int res; char* d = abi::__cxa_demangle(dlinfo.dli_sname, nullptr, nullptr, &res); # else char* d = NULL; # endif - if (!d) fputs(dlinfo.dli_sname, FD); - else fputs(d, FD); + if (!d) OS << dlinfo.dli_sname; + else OS << d; free(d); // FIXME: When we move to C++11, use %t length modifier. It's not in // C++03 and causes gcc to issue warnings. Losing the upper 32 bits of // the stack offset for a stack dump isn't likely to cause any problems. - fprintf(FD, " + %u",(unsigned)((char*)StackTrace[i]- - (char*)dlinfo.dli_saddr)); + OS << format(" + %u",(unsigned)((char*)StackTrace[i]- + (char*)dlinfo.dli_saddr)); } - fputc('\n', FD); + OS << '\n'; } #else backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO); @@ -468,17 +491,19 @@ void llvm::sys::PrintStackTrace(FILE *FD) { } static void PrintStackTraceSignalHandler(void *) { - PrintStackTrace(stderr); + PrintStackTrace(llvm::errs()); } +void llvm::sys::DisableSystemDialogsOnCrash() {} + /// PrintStackTraceOnErrorSignal - When an error signal (such as SIGABRT or /// SIGSEGV) is delivered to the process, print a stack trace and then exit. -void llvm::sys::PrintStackTraceOnErrorSignal() { +void llvm::sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) { AddSignalHandler(PrintStackTraceSignalHandler, nullptr); #if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES) // Environment variable to disable any kind of crash dialog. - if (getenv("LLVM_DISABLE_CRASH_REPORT")) { + if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) { mach_port_t self = mach_task_self(); exception_mask_t mask = EXC_MASK_CRASH;