diff --git a/include/llvm/System/Signals.h b/include/llvm/System/Signals.h index f29fae9ab54..1d5286f3bd9 100644 --- a/include/llvm/System/Signals.h +++ b/include/llvm/System/Signals.h @@ -42,7 +42,8 @@ namespace sys { /// being killed, and the interrupt function automatically disabled. Note /// that interrupt functions are not allowed to call any non-reentrant /// functions. An null interrupt function pointer disables the current - /// installed function. + /// installed function. Note also that the handler may be executed on a + /// different thread on some platforms. /// @brief Register a function to be called when ctrl-c is pressed. void SetInterruptFunction(void (*IF)()); } // End sys namespace diff --git a/lib/System/Win32/Signals.inc b/lib/System/Win32/Signals.inc index a2c7ae2c307..cf5cb40d4d0 100644 --- a/lib/System/Win32/Signals.inc +++ b/lib/System/Win32/Signals.inc @@ -29,6 +29,9 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); +// InterruptFunction - The function to call if ctrl-c is pressed. +static void (*InterruptFunction)() = 0; + static std::vector *FilesToRemove = NULL; static std::vector *DirectoriesToRemove = NULL; static bool RegisteredUnhandledExceptionFilter = false; @@ -111,7 +114,9 @@ void sys::PrintStackTraceOnErrorSignal() { void sys::SetInterruptFunction(void (*IF)()) { - // Currently unimplemented. + InterruptFunction = IF; + RegisterHandler(); + LeaveCriticalSection(&CriticalSection); } } @@ -234,9 +239,28 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { } static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { + EnterCriticalSection(&CriticalSection); Cleanup(); + // If an interrupt function has been set, go and run one it; otherwise, + // the process dies. + void (*IF)() = InterruptFunction; + InterruptFunction = 0; // Don't run it on another CTRL-C. + + if (IF) { + try { + IF(); // Run it now. + } catch (...) { + // Kill the process on an exception. + LeaveCriticalSection(&CriticalSection); + return FALSE; + } + LeaveCriticalSection(&CriticalSection); + return TRUE; // Don't kill the process. + } + // Allow normal processing to take place; i.e., the process dies. + LeaveCriticalSection(&CriticalSection); return FALSE; }