diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Support/Unix/Process.inc | 24 | ||||
-rw-r--r-- | llvm/lib/Support/Windows/Process.inc | 6 | ||||
-rw-r--r-- | llvm/lib/Support/raw_ostream.cpp | 15 |
3 files changed, 34 insertions, 11 deletions
diff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc index 01c78cbc0da..d39443b1124 100644 --- a/llvm/lib/Support/Unix/Process.inc +++ b/llvm/lib/Support/Unix/Process.inc @@ -258,6 +258,30 @@ std::error_code Process::FixupStandardFileDescriptors() { return std::error_code(); } +std::error_code Process::SafelyCloseFileDescriptor(int FD) { + // Create a signal set filled with *all* signals. + sigset_t FullSet; + if (sigfillset(&FullSet) < 0) + return std::error_code(errno, std::generic_category()); + // Atomically swap our current signal mask with a full mask. + sigset_t SavedSet; + if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet)) + return std::error_code(EC, std::generic_category()); + // Attempt to close the file descriptor. + // We need to save the error, if one occurs, because our subsequent call to + // pthread_sigmask might tamper with errno. + int ErrnoFromClose = 0; + if (::close(FD) < 0) + ErrnoFromClose = errno; + // Restore the signal mask back to what we saved earlier. + int EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr); + // The error code from close takes precedence over the one from + // pthread_sigmask. + if (ErrnoFromClose) + return std::error_code(ErrnoFromClose, std::generic_category()); + return std::error_code(EC, std::generic_category()); +} + bool Process::StandardInIsUserInput() { return FileDescriptorIsDisplayed(STDIN_FILENO); } diff --git a/llvm/lib/Support/Windows/Process.inc b/llvm/lib/Support/Windows/Process.inc index db87d8ed60e..3819e638c72 100644 --- a/llvm/lib/Support/Windows/Process.inc +++ b/llvm/lib/Support/Windows/Process.inc @@ -277,6 +277,12 @@ std::error_code Process::FixupStandardFileDescriptors() { return std::error_code(); } +std::error_code Process::SafelyCloseFileDescriptor(int FD) { + if (::close(FD) < 0) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + bool Process::StandardInIsUserInput() { return FileDescriptorIsDisplayed(0); } diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index c2c55cff7ed..bbbbe4ae8c6 100644 --- a/llvm/lib/Support/raw_ostream.cpp +++ b/llvm/lib/Support/raw_ostream.cpp @@ -536,12 +536,8 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) raw_fd_ostream::~raw_fd_ostream() { if (FD >= 0) { flush(); - if (ShouldClose) - while (::close(FD) != 0) - if (errno != EINTR) { - error_detected(); - break; - } + if (ShouldClose && sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(); } #ifdef __MINGW32__ @@ -615,11 +611,8 @@ void raw_fd_ostream::close() { assert(ShouldClose); ShouldClose = false; flush(); - while (::close(FD) != 0) - if (errno != EINTR) { - error_detected(); - break; - } + if (sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(); FD = -1; } |