From: Yunzhong Gao Date: Wed, 6 Jan 2016 00:50:06 +0000 (+0000) Subject: Fixing PR25717: fatal IO error writing large outputs to console on Windows. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=46ee2eb7c71ad894dff6ae190cee878dd6ed8192;p=oota-llvm.git Fixing PR25717: fatal IO error writing large outputs to console on Windows. This patch is similar to the Python issue#11395. We need to cap the output size to 32767 on Windows to work around the size limit of WriteConsole(). Reference: https://bugs.python.org/issue11395 Writing a test for this bug turns out to be harder than I thought. I am still working on it (see phabricator review D15705). Differential Revision: http://reviews.llvm.org/D15553 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256892 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Support/Windows/WindowsSupport.h b/lib/Support/Windows/WindowsSupport.h index 34d961b148d..5e5163b3493 100644 --- a/lib/Support/Windows/WindowsSupport.h +++ b/lib/Support/Windows/WindowsSupport.h @@ -30,6 +30,8 @@ #define _WIN32_WINNT 0x0601 #define _WIN32_IE 0x0800 // MinGW at it again. FIXME: verify if still needed. #define WIN32_LEAN_AND_MEAN +#define NOGDI +#define NOMINMAX #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -44,6 +46,20 @@ #include #include +#ifndef __CYGWIN__ +#include +#else +// Cygwin does not have the IsWindows8OrGreater() API. +inline bool IsWindows8OrGreater() { + OSVERSIONINFO osvi = {}; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!::GetVersionEx(&osvi)) + return false; + return (osvi.dwMajorVersion > 6 || + (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 2)); +} +#endif // __CYGWIN__ + inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) { if (!ErrMsg) return true; diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index 57c7ac32f55..57162dc6e95 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -57,6 +57,10 @@ #endif #endif +#ifdef LLVM_ON_WIN32 +#include "Windows/WindowsSupport.h" +#endif + using namespace llvm; raw_ostream::~raw_ostream() { @@ -567,8 +571,21 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { assert(FD >= 0 && "File already closed."); pos += Size; +#ifndef LLVM_ON_WIN32 + bool ShouldWriteInChunks = false; +#else + // Writing a large size of output to Windows console returns ENOMEM. It seems + // that, prior to Windows 8, WriteFile() is redirecting to WriteConsole(), and + // the latter has a size limit (66000 bytes or less, depending on heap usage). + bool ShouldWriteInChunks = !!::_isatty(FD) && !IsWindows8OrGreater(); +#endif + do { - ssize_t ret = ::write(FD, Ptr, Size); + size_t ChunkSize = Size; + if (ChunkSize > 32767 && ShouldWriteInChunks) + ChunkSize = 32767; + + ssize_t ret = ::write(FD, Ptr, ChunkSize); if (ret < 0) { // If it's a recoverable error, swallow it and retry the write.