diff options
author | Brad King <brad.king@kitware.com> | 2019-05-03 15:48:33 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2019-05-03 15:48:46 (GMT) |
commit | 186ca170da51d64a50bb15bfd067ca9b4c987327 (patch) | |
tree | 7e24dcdf673e68d182f4505d55fa614b9da2f7a2 | |
parent | 6f242acfcb72881d184f5b2468fd4ddcadce01d8 (diff) | |
parent | c85524a94ace9ee400229fede179a605b1c144e3 (diff) | |
download | CMake-186ca170da51d64a50bb15bfd067ca9b4c987327.zip CMake-186ca170da51d64a50bb15bfd067ca9b4c987327.tar.gz CMake-186ca170da51d64a50bb15bfd067ca9b4c987327.tar.bz2 |
Merge topic 'std-pipes-always'
c85524a94a Ensure stdin, stdout, and stderr pipes are always open
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Kyle Edwards <kyle.edwards@kitware.com>
Merge-request: !3282
-rw-r--r-- | Source/CPack/cpack.cxx | 1 | ||||
-rw-r--r-- | Source/CursesDialog/ccmake.cxx | 1 | ||||
-rw-r--r-- | Source/QtDialog/CMakeSetup.cxx | 1 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 68 | ||||
-rw-r--r-- | Source/cmSystemTools.h | 2 | ||||
-rw-r--r-- | Source/cmakemain.cxx | 1 | ||||
-rw-r--r-- | Source/ctest.cxx | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 4 |
8 files changed, 77 insertions, 2 deletions
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 3ceb824..58b9e70 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -98,6 +98,7 @@ static void cpackProgressCallback(const std::string& message, float /*unused*/) // this is CPack. int main(int argc, char const* const* argv) { + cmSystemTools::EnsureStdPipes(); #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) // Replace streambuf so we can output Unicode to console cmsys::ConsoleBuf::Manager consoleOut(std::cout); diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 745c6bb..7caed0c 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -67,6 +67,7 @@ void onsig(int /*unused*/) int main(int argc, char const* const* argv) { + cmSystemTools::EnsureStdPipes(); cmsys::Encoding::CommandLineArguments encoding_args = cmsys::Encoding::CommandLineArguments::Main(argc, argv); argc = encoding_args.argc(); diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 8d9a50c..c9ebba8 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -55,6 +55,7 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin); int main(int argc, char** argv) { + cmSystemTools::EnsureStdPipes(); cmsys::Encoding::CommandLineArguments encoding_args = cmsys::Encoding::CommandLineArguments::Main(argc, argv); int argc2 = encoding_args.argc(); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index bc853b7..17ed3f6 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -43,6 +43,7 @@ #include <assert.h> #include <ctype.h> #include <errno.h> +#include <fcntl.h> #include <iostream> #include <sstream> #include <stdio.h> @@ -56,8 +57,6 @@ # include <windows.h> // include wincrypt.h after windows.h # include <wincrypt.h> - -# include <fcntl.h> /* _O_TEXT */ #else # include <sys/time.h> # include <unistd.h> @@ -2007,6 +2006,71 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, } } +#ifdef _WIN32 +static void EnsureStdPipe(DWORD fd) +{ + if (GetStdHandle(fd) != INVALID_HANDLE_VALUE) { + return; + } + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + HANDLE h = CreateFileW( + L"NUL", + fd == STD_INPUT_HANDLE ? FILE_GENERIC_READ + : FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, 0, NULL); + + if (h == INVALID_HANDLE_VALUE) { + LPSTR message = NULL; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message, 0, NULL); + std::string msg = std::string(message, size); + LocalFree(message); + std::cerr << "failed to open NUL for missing stdio pipe: " << msg; + abort(); + } + + SetStdHandle(fd, h); +} + +void cmSystemTools::EnsureStdPipes() +{ + EnsureStdPipe(STD_INPUT_HANDLE); + EnsureStdPipe(STD_OUTPUT_HANDLE); + EnsureStdPipe(STD_ERROR_HANDLE); +} +#else +static void EnsureStdPipe(int fd) +{ + if (fcntl(fd, F_GETFD) != -1 || errno != EBADF) { + return; + } + + int f = open("/dev/null", fd == STDIN_FILENO ? O_RDONLY : O_WRONLY); + if (f == -1) { + perror("failed to open /dev/null for missing stdio pipe"); + abort(); + } + if (f != fd) { + dup2(f, fd); + close(f); + } +} + +void cmSystemTools::EnsureStdPipes() +{ + EnsureStdPipe(STDIN_FILENO); + EnsureStdPipe(STDOUT_FILENO); + EnsureStdPipe(STDERR_FILENO); +} +#endif + void cmSystemTools::DoNotInheritStdPipes() { #ifdef _WIN32 diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 05bd351..8a87a37 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -435,6 +435,8 @@ public: // not get stuck waiting for all the output on the pipes. static void DoNotInheritStdPipes(); + static void EnsureStdPipes(); + /** Copy the file create/access/modify times from the file named by the first argument to that named by the second. */ static bool CopyFileTime(const std::string& fromFile, diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 49d160c..e639c66 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -184,6 +184,7 @@ static void cmakemainProgressCallback(const std::string& m, float prog, int main(int ac, char const* const* av) { + cmSystemTools::EnsureStdPipes(); #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) // Replace streambuf so we can output Unicode to console cmsys::ConsoleBuf::Manager consoleOut(std::cout); diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 461021b..3b3630f 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -143,6 +143,7 @@ static const char* cmDocumentationOptions[][2] = { // this is a test driver program for cmCTest. int main(int argc, char const* const* argv) { + cmSystemTools::EnsureStdPipes(); #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) // Replace streambuf so we can output Unicode to console cmsys::ConsoleBuf::Manager consoleOut(std::cout); diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 49d3608..b9aa536 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -451,4 +451,8 @@ function(reject_fifo) endfunction() if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN") reject_fifo() + run_cmake_command(closed_stdin sh -c "\"${CMAKE_COMMAND}\" --version <&-") + run_cmake_command(closed_stdout sh -c "\"${CMAKE_COMMAND}\" --version >&-") + run_cmake_command(closed_stderr sh -c "\"${CMAKE_COMMAND}\" --version 2>&-") + run_cmake_command(closed_stdall sh -c "\"${CMAKE_COMMAND}\" --version <&- >&- 2>&-") endif() |