Signals.inc revision 261991
1218885Sdim//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file provides the Win32 specific implementation of the Signals class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14261991Sdim#include "llvm/Support/FileSystem.h" 15261991Sdim 16218885Sdim#include "Windows.h" 17249423Sdim#include <algorithm> 18218885Sdim#include <stdio.h> 19218885Sdim#include <vector> 20218885Sdim 21218885Sdim#ifdef __MINGW32__ 22218885Sdim #include <imagehlp.h> 23218885Sdim#else 24218885Sdim #include <dbghelp.h> 25218885Sdim#endif 26218885Sdim#include <psapi.h> 27218885Sdim 28226633Sdim#ifdef _MSC_VER 29226633Sdim #pragma comment(lib, "psapi.lib") 30226633Sdim #pragma comment(lib, "dbghelp.lib") 31226633Sdim#elif __MINGW32__ 32218885Sdim #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1)) 33218885Sdim #error "libimagehlp.a & libpsapi.a should be present" 34218885Sdim #endif 35226633Sdim // The version of g++ that comes with MinGW does *not* properly understand 36226633Sdim // the ll format specifier for printf. However, MinGW passes the format 37226633Sdim // specifiers on to the MSVCRT entirely, and the CRT understands the ll 38226633Sdim // specifier. So these warnings are spurious in this case. Since we compile 39226633Sdim // with -Wall, this will generate these warnings which should be ignored. So 40226633Sdim // we will turn off the warnings for this just file. However, MinGW also does 41226633Sdim // not support push and pop for diagnostics, so we have to manually turn it 42226633Sdim // back on at the end of the file. 43226633Sdim #pragma GCC diagnostic ignored "-Wformat" 44226633Sdim #pragma GCC diagnostic ignored "-Wformat-extra-args" 45218885Sdim 46226633Sdim #if !defined(__MINGW64_VERSION_MAJOR) 47226633Sdim // MinGW.org does not have updated support for the 64-bit versions of the 48226633Sdim // DebugHlp APIs. So we will have to load them manually. The structures and 49226633Sdim // method signatures were pulled from DbgHelp.h in the Windows Platform SDK, 50226633Sdim // and adjusted for brevity. 51226633Sdim typedef struct _IMAGEHLP_LINE64 { 52226633Sdim DWORD SizeOfStruct; 53226633Sdim PVOID Key; 54226633Sdim DWORD LineNumber; 55226633Sdim PCHAR FileName; 56226633Sdim DWORD64 Address; 57226633Sdim } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; 58226633Sdim 59226633Sdim typedef struct _IMAGEHLP_SYMBOL64 { 60226633Sdim DWORD SizeOfStruct; 61226633Sdim DWORD64 Address; 62226633Sdim DWORD Size; 63226633Sdim DWORD Flags; 64226633Sdim DWORD MaxNameLength; 65226633Sdim CHAR Name[1]; 66226633Sdim } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; 67226633Sdim 68226633Sdim typedef struct _tagADDRESS64 { 69226633Sdim DWORD64 Offset; 70226633Sdim WORD Segment; 71226633Sdim ADDRESS_MODE Mode; 72226633Sdim } ADDRESS64, *LPADDRESS64; 73226633Sdim 74226633Sdim typedef struct _KDHELP64 { 75226633Sdim DWORD64 Thread; 76226633Sdim DWORD ThCallbackStack; 77226633Sdim DWORD ThCallbackBStore; 78226633Sdim DWORD NextCallback; 79226633Sdim DWORD FramePointer; 80226633Sdim DWORD64 KiCallUserMode; 81226633Sdim DWORD64 KeUserCallbackDispatcher; 82226633Sdim DWORD64 SystemRangeStart; 83226633Sdim DWORD64 KiUserExceptionDispatcher; 84226633Sdim DWORD64 StackBase; 85226633Sdim DWORD64 StackLimit; 86226633Sdim DWORD64 Reserved[5]; 87226633Sdim } KDHELP64, *PKDHELP64; 88226633Sdim 89226633Sdim typedef struct _tagSTACKFRAME64 { 90226633Sdim ADDRESS64 AddrPC; 91226633Sdim ADDRESS64 AddrReturn; 92226633Sdim ADDRESS64 AddrFrame; 93226633Sdim ADDRESS64 AddrStack; 94226633Sdim ADDRESS64 AddrBStore; 95226633Sdim PVOID FuncTableEntry; 96226633Sdim DWORD64 Params[4]; 97226633Sdim BOOL Far; 98226633Sdim BOOL Virtual; 99226633Sdim DWORD64 Reserved[3]; 100226633Sdim KDHELP64 KdHelp; 101226633Sdim } STACKFRAME64, *LPSTACKFRAME64; 102226633Sdim 103226633Sdimtypedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, 104226633Sdim DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, 105226633Sdim LPDWORD lpNumberOfBytesRead); 106226633Sdim 107226633Sdimtypedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, 108226633Sdim DWORD64 AddrBase); 109226633Sdim 110226633Sdimtypedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, 111226633Sdim DWORD64 Address); 112226633Sdim 113226633Sdimtypedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, 114226633Sdim HANDLE hThread, LPADDRESS64 lpaddr); 115226633Sdim 116226633Sdimtypedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, 117226633Sdim PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, 118226633Sdim PFUNCTION_TABLE_ACCESS_ROUTINE64, 119226633Sdim PGET_MODULE_BASE_ROUTINE64, 120226633Sdim PTRANSLATE_ADDRESS_ROUTINE64); 121226633Sdimstatic fpStackWalk64 StackWalk64; 122226633Sdim 123226633Sdimtypedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); 124226633Sdimstatic fpSymGetModuleBase64 SymGetModuleBase64; 125226633Sdim 126226633Sdimtypedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, 127226633Sdim PDWORD64, PIMAGEHLP_SYMBOL64); 128226633Sdimstatic fpSymGetSymFromAddr64 SymGetSymFromAddr64; 129226633Sdim 130226633Sdimtypedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, 131226633Sdim PDWORD, PIMAGEHLP_LINE64); 132226633Sdimstatic fpSymGetLineFromAddr64 SymGetLineFromAddr64; 133226633Sdim 134226633Sdimtypedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); 135226633Sdimstatic fpSymFunctionTableAccess64 SymFunctionTableAccess64; 136226633Sdim 137226633Sdimstatic bool load64BitDebugHelp(void) { 138261991Sdim HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll"); 139226633Sdim if (hLib) { 140226633Sdim StackWalk64 = (fpStackWalk64) 141226633Sdim ::GetProcAddress(hLib, "StackWalk64"); 142226633Sdim SymGetModuleBase64 = (fpSymGetModuleBase64) 143226633Sdim ::GetProcAddress(hLib, "SymGetModuleBase64"); 144226633Sdim SymGetSymFromAddr64 = (fpSymGetSymFromAddr64) 145226633Sdim ::GetProcAddress(hLib, "SymGetSymFromAddr64"); 146226633Sdim SymGetLineFromAddr64 = (fpSymGetLineFromAddr64) 147226633Sdim ::GetProcAddress(hLib, "SymGetLineFromAddr64"); 148226633Sdim SymFunctionTableAccess64 = (fpSymFunctionTableAccess64) 149226633Sdim ::GetProcAddress(hLib, "SymFunctionTableAccess64"); 150226633Sdim } 151226633Sdim return StackWalk64 != NULL; 152226633Sdim} 153226633Sdim #endif // !defined(__MINGW64_VERSION_MAJOR) 154226633Sdim#endif // __MINGW32__ 155226633Sdim 156218885Sdim// Forward declare. 157218885Sdimstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); 158218885Sdimstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); 159218885Sdim 160218885Sdim// InterruptFunction - The function to call if ctrl-c is pressed. 161218885Sdimstatic void (*InterruptFunction)() = 0; 162218885Sdim 163261991Sdimstatic std::vector<std::string> *FilesToRemove = NULL; 164218885Sdimstatic std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0; 165218885Sdimstatic bool RegisteredUnhandledExceptionFilter = false; 166218885Sdimstatic bool CleanupExecuted = false; 167218885Sdimstatic bool ExitOnUnhandledExceptions = false; 168218885Sdimstatic PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; 169218885Sdim 170218885Sdim// Windows creates a new thread to execute the console handler when an event 171218885Sdim// (such as CTRL/C) occurs. This causes concurrency issues with the above 172218885Sdim// globals which this critical section addresses. 173218885Sdimstatic CRITICAL_SECTION CriticalSection; 174218885Sdim 175218885Sdimnamespace llvm { 176218885Sdim 177218885Sdim//===----------------------------------------------------------------------===// 178218885Sdim//=== WARNING: Implementation here must contain only Win32 specific code 179218885Sdim//=== and must not be UNIX code 180218885Sdim//===----------------------------------------------------------------------===// 181218885Sdim 182218885Sdim#ifdef _MSC_VER 183251662Sdim/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry, 184251662Sdim/// ignore" CRT debug report dialog. "retry" raises an exception which 185251662Sdim/// ultimately triggers our stack dumper. 186251662Sdimstatic int AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { 187251662Sdim // Set *Return to the retry code for the return value of _CrtDbgReport: 188251662Sdim // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx 189251662Sdim // This may also trigger just-in-time debugging via DebugBreak(). 190251662Sdim if (Return) 191251662Sdim *Return = 1; 192251662Sdim // Don't call _CrtDbgReport. 193251662Sdim return TRUE; 194251662Sdim} 195251662Sdim 196218885Sdim#endif 197218885Sdim 198218885Sdimstatic void RegisterHandler() { 199226633Sdim#if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR) 200226633Sdim // On MinGW.org, we need to load up the symbols explicitly, because the 201226633Sdim // Win32 framework they include does not have support for the 64-bit 202226633Sdim // versions of the APIs we need. If we cannot load up the APIs (which 203226633Sdim // would be unexpected as they should exist on every version of Windows 204226633Sdim // we support), we will bail out since there would be nothing to report. 205226633Sdim if (!load64BitDebugHelp()) { 206226633Sdim assert(false && "These APIs should always be available"); 207226633Sdim return; 208226633Sdim } 209226633Sdim#endif 210226633Sdim 211218885Sdim if (RegisteredUnhandledExceptionFilter) { 212218885Sdim EnterCriticalSection(&CriticalSection); 213218885Sdim return; 214218885Sdim } 215218885Sdim 216218885Sdim // Now's the time to create the critical section. This is the first time 217218885Sdim // through here, and there's only one thread. 218218885Sdim InitializeCriticalSection(&CriticalSection); 219218885Sdim 220218885Sdim // Enter it immediately. Now if someone hits CTRL/C, the console handler 221218885Sdim // can't proceed until the globals are updated. 222218885Sdim EnterCriticalSection(&CriticalSection); 223218885Sdim 224218885Sdim RegisteredUnhandledExceptionFilter = true; 225218885Sdim OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); 226218885Sdim SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); 227218885Sdim 228218885Sdim // Environment variable to disable any kind of crash dialog. 229234353Sdim if (getenv("LLVM_DISABLE_CRASH_REPORT")) { 230218885Sdim#ifdef _MSC_VER 231261991Sdim _CrtSetReportHook(AvoidMessageBoxHook); 232218885Sdim#endif 233218885Sdim SetErrorMode(SEM_FAILCRITICALERRORS | 234218885Sdim SEM_NOGPFAULTERRORBOX | 235218885Sdim SEM_NOOPENFILEERRORBOX); 236218885Sdim ExitOnUnhandledExceptions = true; 237218885Sdim } 238218885Sdim 239218885Sdim // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or 240218885Sdim // else multi-threading problems will ensue. 241218885Sdim} 242218885Sdim 243218885Sdim// RemoveFileOnSignal - The public API 244261991Sdimbool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { 245218885Sdim RegisterHandler(); 246218885Sdim 247218885Sdim if (CleanupExecuted) { 248218885Sdim if (ErrMsg) 249218885Sdim *ErrMsg = "Process terminating -- cannot register for removal"; 250218885Sdim return true; 251218885Sdim } 252218885Sdim 253218885Sdim if (FilesToRemove == NULL) 254261991Sdim FilesToRemove = new std::vector<std::string>; 255218885Sdim 256218885Sdim FilesToRemove->push_back(Filename); 257218885Sdim 258218885Sdim LeaveCriticalSection(&CriticalSection); 259218885Sdim return false; 260218885Sdim} 261218885Sdim 262218885Sdim// DontRemoveFileOnSignal - The public API 263261991Sdimvoid sys::DontRemoveFileOnSignal(StringRef Filename) { 264218885Sdim if (FilesToRemove == NULL) 265218885Sdim return; 266218885Sdim 267218885Sdim RegisterHandler(); 268218885Sdim 269218885Sdim FilesToRemove->push_back(Filename); 270261991Sdim std::vector<std::string>::reverse_iterator I = 271218885Sdim std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); 272218885Sdim if (I != FilesToRemove->rend()) 273218885Sdim FilesToRemove->erase(I.base()-1); 274218885Sdim 275218885Sdim LeaveCriticalSection(&CriticalSection); 276218885Sdim} 277218885Sdim 278218885Sdim/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or 279218885Sdim/// SIGSEGV) is delivered to the process, print a stack trace and then exit. 280218885Sdimvoid sys::PrintStackTraceOnErrorSignal() { 281218885Sdim RegisterHandler(); 282218885Sdim LeaveCriticalSection(&CriticalSection); 283218885Sdim} 284218885Sdim 285249423Sdimvoid llvm::sys::PrintStackTrace(FILE *) { 286249423Sdim // FIXME: Implement. 287249423Sdim} 288218885Sdim 289249423Sdim 290218885Sdimvoid sys::SetInterruptFunction(void (*IF)()) { 291218885Sdim RegisterHandler(); 292218885Sdim InterruptFunction = IF; 293218885Sdim LeaveCriticalSection(&CriticalSection); 294218885Sdim} 295218885Sdim 296218885Sdim 297218885Sdim/// AddSignalHandler - Add a function to be called when a signal is delivered 298218885Sdim/// to the process. The handler can have a cookie passed to it to identify 299218885Sdim/// what instance of the handler it is. 300218885Sdimvoid sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { 301218885Sdim if (CallBacksToRun == 0) 302218885Sdim CallBacksToRun = new std::vector<std::pair<void(*)(void*), void*> >(); 303218885Sdim CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); 304218885Sdim RegisterHandler(); 305218885Sdim LeaveCriticalSection(&CriticalSection); 306218885Sdim} 307218885Sdim} 308218885Sdim 309218885Sdimstatic void Cleanup() { 310218885Sdim EnterCriticalSection(&CriticalSection); 311218885Sdim 312218885Sdim // Prevent other thread from registering new files and directories for 313218885Sdim // removal, should we be executing because of the console handler callback. 314218885Sdim CleanupExecuted = true; 315218885Sdim 316218885Sdim // FIXME: open files cannot be deleted. 317218885Sdim 318218885Sdim if (FilesToRemove != NULL) 319218885Sdim while (!FilesToRemove->empty()) { 320261991Sdim bool Existed; 321261991Sdim llvm::sys::fs::remove(FilesToRemove->back(), Existed); 322218885Sdim FilesToRemove->pop_back(); 323218885Sdim } 324218885Sdim 325218885Sdim if (CallBacksToRun) 326218885Sdim for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) 327218885Sdim (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second); 328218885Sdim 329218885Sdim LeaveCriticalSection(&CriticalSection); 330218885Sdim} 331218885Sdim 332218885Sdimvoid llvm::sys::RunInterruptHandlers() { 333218885Sdim Cleanup(); 334218885Sdim} 335218885Sdim 336218885Sdimstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 337218885Sdim Cleanup(); 338218885Sdim 339218885Sdim // Initialize the STACKFRAME structure. 340226633Sdim STACKFRAME64 StackFrame; 341218885Sdim memset(&StackFrame, 0, sizeof(StackFrame)); 342218885Sdim 343226633Sdim DWORD machineType; 344226633Sdim#if defined(_M_X64) 345226633Sdim machineType = IMAGE_FILE_MACHINE_AMD64; 346226633Sdim StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; 347226633Sdim StackFrame.AddrPC.Mode = AddrModeFlat; 348226633Sdim StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; 349226633Sdim StackFrame.AddrStack.Mode = AddrModeFlat; 350226633Sdim StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; 351226633Sdim StackFrame.AddrFrame.Mode = AddrModeFlat; 352226633Sdim#elif defined(_M_IX86) 353226633Sdim machineType = IMAGE_FILE_MACHINE_I386; 354218885Sdim StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; 355218885Sdim StackFrame.AddrPC.Mode = AddrModeFlat; 356218885Sdim StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; 357218885Sdim StackFrame.AddrStack.Mode = AddrModeFlat; 358218885Sdim StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; 359218885Sdim StackFrame.AddrFrame.Mode = AddrModeFlat; 360226633Sdim#endif 361218885Sdim 362218885Sdim HANDLE hProcess = GetCurrentProcess(); 363218885Sdim HANDLE hThread = GetCurrentThread(); 364218885Sdim 365218885Sdim // Initialize the symbol handler. 366218885Sdim SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES); 367218885Sdim SymInitialize(hProcess, NULL, TRUE); 368218885Sdim 369218885Sdim while (true) { 370226633Sdim if (!StackWalk64(machineType, hProcess, hThread, &StackFrame, 371226633Sdim ep->ContextRecord, NULL, SymFunctionTableAccess64, 372226633Sdim SymGetModuleBase64, NULL)) { 373218885Sdim break; 374218885Sdim } 375218885Sdim 376218885Sdim if (StackFrame.AddrFrame.Offset == 0) 377218885Sdim break; 378218885Sdim 379218885Sdim // Print the PC in hexadecimal. 380226633Sdim DWORD64 PC = StackFrame.AddrPC.Offset; 381226633Sdim#if defined(_M_X64) 382226633Sdim fprintf(stderr, "0x%016llX", PC); 383226633Sdim#elif defined(_M_IX86) 384226633Sdim fprintf(stderr, "0x%08lX", static_cast<DWORD>(PC)); 385226633Sdim#endif 386218885Sdim 387218885Sdim // Print the parameters. Assume there are four. 388226633Sdim#if defined(_M_X64) 389226633Sdim fprintf(stderr, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", 390226633Sdim StackFrame.Params[0], 391226633Sdim StackFrame.Params[1], 392226633Sdim StackFrame.Params[2], 393226633Sdim StackFrame.Params[3]); 394226633Sdim#elif defined(_M_IX86) 395218885Sdim fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", 396226633Sdim static_cast<DWORD>(StackFrame.Params[0]), 397226633Sdim static_cast<DWORD>(StackFrame.Params[1]), 398226633Sdim static_cast<DWORD>(StackFrame.Params[2]), 399226633Sdim static_cast<DWORD>(StackFrame.Params[3])); 400226633Sdim#endif 401218885Sdim // Verify the PC belongs to a module in this process. 402226633Sdim if (!SymGetModuleBase64(hProcess, PC)) { 403218885Sdim fputs(" <unknown module>\n", stderr); 404218885Sdim continue; 405218885Sdim } 406218885Sdim 407218885Sdim // Print the symbol name. 408218885Sdim char buffer[512]; 409226633Sdim IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); 410226633Sdim memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); 411226633Sdim symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 412226633Sdim symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); 413218885Sdim 414226633Sdim DWORD64 dwDisp; 415226633Sdim if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { 416218885Sdim fputc('\n', stderr); 417218885Sdim continue; 418218885Sdim } 419218885Sdim 420218885Sdim buffer[511] = 0; 421218885Sdim if (dwDisp > 0) 422226633Sdim fprintf(stderr, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp); 423218885Sdim else 424218885Sdim fprintf(stderr, ", %s", symbol->Name); 425218885Sdim 426218885Sdim // Print the source file and line number information. 427226633Sdim IMAGEHLP_LINE64 line; 428226633Sdim DWORD dwLineDisp; 429218885Sdim memset(&line, 0, sizeof(line)); 430218885Sdim line.SizeOfStruct = sizeof(line); 431226633Sdim if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { 432218885Sdim fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber); 433226633Sdim if (dwLineDisp > 0) 434226633Sdim fprintf(stderr, " + 0x%lX byte(s)", dwLineDisp); 435218885Sdim } 436218885Sdim 437218885Sdim fputc('\n', stderr); 438218885Sdim } 439218885Sdim 440218885Sdim if (ExitOnUnhandledExceptions) 441234353Sdim _exit(ep->ExceptionRecord->ExceptionCode); 442218885Sdim 443218885Sdim // Allow dialog box to pop up allowing choice to start debugger. 444218885Sdim if (OldFilter) 445218885Sdim return (*OldFilter)(ep); 446218885Sdim else 447218885Sdim return EXCEPTION_CONTINUE_SEARCH; 448218885Sdim} 449218885Sdim 450218885Sdimstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { 451218885Sdim // We are running in our very own thread, courtesy of Windows. 452218885Sdim EnterCriticalSection(&CriticalSection); 453218885Sdim Cleanup(); 454218885Sdim 455218885Sdim // If an interrupt function has been set, go and run one it; otherwise, 456218885Sdim // the process dies. 457218885Sdim void (*IF)() = InterruptFunction; 458218885Sdim InterruptFunction = 0; // Don't run it on another CTRL-C. 459218885Sdim 460218885Sdim if (IF) { 461218885Sdim // Note: if the interrupt function throws an exception, there is nothing 462218885Sdim // to catch it in this thread so it will kill the process. 463218885Sdim IF(); // Run it now. 464218885Sdim LeaveCriticalSection(&CriticalSection); 465218885Sdim return TRUE; // Don't kill the process. 466218885Sdim } 467218885Sdim 468218885Sdim // Allow normal processing to take place; i.e., the process dies. 469218885Sdim LeaveCriticalSection(&CriticalSection); 470218885Sdim return FALSE; 471218885Sdim} 472226633Sdim 473226633Sdim#if __MINGW32__ 474226633Sdim // We turned these warnings off for this file so that MinGW-g++ doesn't 475226633Sdim // complain about the ll format specifiers used. Now we are turning the 476226633Sdim // warnings back on. If MinGW starts to support diagnostic stacks, we can 477226633Sdim // replace this with a pop. 478226633Sdim #pragma GCC diagnostic warning "-Wformat" 479226633Sdim #pragma GCC diagnostic warning "-Wformat-extra-args" 480226633Sdim#endif 481