Skip to content

Commit

Permalink
Merge topic 'std-pipes-always'
Browse files Browse the repository at this point in the history
c85524a Ensure stdin, stdout, and stderr pipes are always open

Acked-by: Kitware Robot <[email protected]>
Acked-by: Kyle Edwards <[email protected]>
Merge-request: !3282
  • Loading branch information
bradking authored and kwrobot committed May 3, 2019
2 parents 6f242ac + c85524a commit 186ca17
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 2 deletions.
1 change: 1 addition & 0 deletions Source/CPack/cpack.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions Source/CursesDialog/ccmake.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions Source/QtDialog/CMakeSetup.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
68 changes: 66 additions & 2 deletions Source/cmSystemTools.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <sstream>
#include <stdio.h>
Expand All @@ -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>
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Source/cmSystemTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ class cmSystemTools : public cmsys::SystemTools
// 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,
Expand Down
1 change: 1 addition & 0 deletions Source/cmakemain.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions Source/ctest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions Tests/RunCMake/CommandLine/RunCMakeTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 186ca17

Please sign in to comment.