llvm.org GIT mirror llvm / 46ee2eb
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 Yunzhong Gao 3 years ago
2 changed file(s) with 34 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
2929 #define _WIN32_WINNT 0x0601
3030 #define _WIN32_IE 0x0800 // MinGW at it again. FIXME: verify if still needed.
3131 #define WIN32_LEAN_AND_MEAN
32 #define NOGDI
33 #define NOMINMAX
3234
3335 #include "llvm/ADT/SmallVector.h"
3436 #include "llvm/ADT/StringExtras.h"
4244 #include
4345 #include
4446 #include
47
48 #ifndef __CYGWIN__
49 #include
50 #else
51 // Cygwin does not have the IsWindows8OrGreater() API.
52 inline bool IsWindows8OrGreater() {
53 OSVERSIONINFO osvi = {};
54 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
55 if (!::GetVersionEx(&osvi))
56 return false;
57 return (osvi.dwMajorVersion > 6 ||
58 (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 2));
59 }
60 #endif // __CYGWIN__
4561
4662 inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) {
4763 if (!ErrMsg)
5454 #ifndef STDERR_FILENO
5555 # define STDERR_FILENO 2
5656 #endif
57 #endif
58
59 #ifdef LLVM_ON_WIN32
60 #include "Windows/WindowsSupport.h"
5761 #endif
5862
5963 using namespace llvm;
566570 assert(FD >= 0 && "File already closed.");
567571 pos += Size;
568572
573 #ifndef LLVM_ON_WIN32
574 bool ShouldWriteInChunks = false;
575 #else
576 // Writing a large size of output to Windows console returns ENOMEM. It seems
577 // that, prior to Windows 8, WriteFile() is redirecting to WriteConsole(), and
578 // the latter has a size limit (66000 bytes or less, depending on heap usage).
579 bool ShouldWriteInChunks = !!::_isatty(FD) && !IsWindows8OrGreater();
580 #endif
581
569582 do {
570 ssize_t ret = ::write(FD, Ptr, Size);
583 size_t ChunkSize = Size;
584 if (ChunkSize > 32767 && ShouldWriteInChunks)
585 ChunkSize = 32767;
586
587 ssize_t ret = ::write(FD, Ptr, ChunkSize);
571588
572589 if (ret < 0) {
573590 // If it's a recoverable error, swallow it and retry the write.