summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-05-03 15:48:33 (GMT)
committerKitware Robot <kwrobot@kitware.com>2019-05-03 15:48:46 (GMT)
commit186ca170da51d64a50bb15bfd067ca9b4c987327 (patch)
tree7e24dcdf673e68d182f4505d55fa614b9da2f7a2
parent6f242acfcb72881d184f5b2468fd4ddcadce01d8 (diff)
parentc85524a94ace9ee400229fede179a605b1c144e3 (diff)
downloadCMake-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.cxx1
-rw-r--r--Source/CursesDialog/ccmake.cxx1
-rw-r--r--Source/QtDialog/CMakeSetup.cxx1
-rw-r--r--Source/cmSystemTools.cxx68
-rw-r--r--Source/cmSystemTools.h2
-rw-r--r--Source/cmakemain.cxx1
-rw-r--r--Source/ctest.cxx1
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake4
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()