mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-15 20:46:37 +08:00
Ensure stdin, stdout, and stderr pipes are always open
On non-Windows platforms libuv assumes that file descriptors 0-2 are always used for standard pipes and never for anything else. Otherwise, libuv may re-use one of these descriptors and then fail an assertion when closing it. Similarly, On Windows platforms our ConsoleBuf implementation assumes that the standard handles are always open. If CMake is run with any standard pipes closed, open them with `/dev/null` or `NUL` to satisfy these assumptions. Fixes: #19219
This commit is contained in:
@@ -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);
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -183,6 +183,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);
|
||||
|
@@ -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);
|
||||
|
@@ -443,4 +443,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()
|
||||
|
Reference in New Issue
Block a user