23 changes: 20 additions & 3 deletions llvm/lib/Support/Windows/Signals.inc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ExitCodes.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
Expand Down Expand Up @@ -204,6 +205,9 @@ static bool RegisteredUnhandledExceptionFilter = false;
static bool CleanupExecuted = false;
static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;

/// The function to call on "SIGPIPE" (one-time use only).
static std::atomic<void (*)()> OneShotPipeSignalFunction(nullptr);

// Windows creates a new thread to execute the console handler when an event
// (such as CTRL/C) occurs. This causes concurrency issues with the above
// globals which this critical section addresses.
Expand Down Expand Up @@ -575,11 +579,16 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
}

void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
// Unimplemented.
OneShotPipeSignalFunction.exchange(Handler);
}

void llvm::sys::DefaultOneShotPipeSignalHandler() {
// Unimplemented.
llvm::sys::Process::Exit(EX_IOERR, /*NoCleanup=*/true);
}

void llvm::sys::CallOneShotPipeSignalHandler() {
if (auto OldOneShotPipeFunction = OneShotPipeSignalFunction.exchange(nullptr))
OldOneShotPipeFunction();
}

/// Add a function to be called when a signal is delivered to the process. The
Expand Down Expand Up @@ -816,7 +825,15 @@ WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
}

void sys::CleanupOnSignal(uintptr_t Context) {
LLVMUnhandledExceptionFilter((LPEXCEPTION_POINTERS)Context);
LPEXCEPTION_POINTERS EP = (LPEXCEPTION_POINTERS)Context;
// Broken pipe is not a crash.
//
// 0xE0000000 is combined with the return code in the exception raised in
// CrashRecoveryContext::HandleExit().
int RetCode = (int)EP->ExceptionRecord->ExceptionCode;
if (RetCode == (0xE0000000 | EX_IOERR))
return;
LLVMUnhandledExceptionFilter(EP);
}

static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Support/raw_ostream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

#ifdef _WIN32
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Windows/WindowsSupport.h"
#endif

Expand Down Expand Up @@ -775,6 +776,15 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
)
continue;

#ifdef _WIN32
// Windows equivalents of SIGPIPE/EPIPE.
DWORD WinLastError = GetLastError();
if (WinLastError == ERROR_BROKEN_PIPE ||
(WinLastError == ERROR_NO_DATA && errno == EINVAL)) {
llvm::sys::CallOneShotPipeSignalHandler();
errno = EPIPE;
}
#endif
// Otherwise it's a non-recoverable error. Note it and quit.
error_detected(std::error_code(errno, std::generic_category()));
break;
Expand Down