|
|
@ -43,6 +43,7 @@ |
|
|
|
#include <sys/wait.h> |
|
|
|
#include <sys/wait.h> |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "google/protobuf/stubs/logging.h" |
|
|
|
#include "google/protobuf/stubs/logging.h" |
|
|
|
#include "google/protobuf/stubs/logging.h" |
|
|
|
#include "absl/strings/escaping.h" |
|
|
|
#include "absl/strings/escaping.h" |
|
|
|
#include "absl/strings/substitute.h" |
|
|
|
#include "absl/strings/substitute.h" |
|
|
@ -57,8 +58,8 @@ namespace compiler { |
|
|
|
|
|
|
|
|
|
|
|
static void CloseHandleOrDie(HANDLE handle) { |
|
|
|
static void CloseHandleOrDie(HANDLE handle) { |
|
|
|
if (!CloseHandle(handle)) { |
|
|
|
if (!CloseHandle(handle)) { |
|
|
|
GOOGLE_LOG(FATAL) << "CloseHandle: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "CloseHandle: " |
|
|
|
<< Subprocess::Win32ErrorMessage(GetLastError()); |
|
|
|
<< Subprocess::Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -85,22 +86,22 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { |
|
|
|
HANDLE stdout_pipe_write; |
|
|
|
HANDLE stdout_pipe_write; |
|
|
|
|
|
|
|
|
|
|
|
if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, nullptr, 0)) { |
|
|
|
if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, nullptr, 0)) { |
|
|
|
GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, nullptr, 0)) { |
|
|
|
if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, nullptr, 0)) { |
|
|
|
GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Make child side of the pipes inheritable.
|
|
|
|
// Make child side of the pipes inheritable.
|
|
|
|
if (!SetHandleInformation(stdin_pipe_read, HANDLE_FLAG_INHERIT, |
|
|
|
if (!SetHandleInformation(stdin_pipe_read, HANDLE_FLAG_INHERIT, |
|
|
|
HANDLE_FLAG_INHERIT)) { |
|
|
|
HANDLE_FLAG_INHERIT)) { |
|
|
|
GOOGLE_LOG(FATAL) << "SetHandleInformation: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "SetHandleInformation: " |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!SetHandleInformation(stdout_pipe_write, HANDLE_FLAG_INHERIT, |
|
|
|
if (!SetHandleInformation(stdout_pipe_write, HANDLE_FLAG_INHERIT, |
|
|
|
HANDLE_FLAG_INHERIT)) { |
|
|
|
HANDLE_FLAG_INHERIT)) { |
|
|
|
GOOGLE_LOG(FATAL) << "SetHandleInformation: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "SetHandleInformation: " |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Setup STARTUPINFO to redirect handles.
|
|
|
|
// Setup STARTUPINFO to redirect handles.
|
|
|
@ -113,13 +114,13 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { |
|
|
|
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); |
|
|
|
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); |
|
|
|
|
|
|
|
|
|
|
|
if (startup_info.hStdError == INVALID_HANDLE_VALUE) { |
|
|
|
if (startup_info.hStdError == INVALID_HANDLE_VALUE) { |
|
|
|
GOOGLE_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError()); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// get wide string version of program as the path may contain non-ascii characters
|
|
|
|
// get wide string version of program as the path may contain non-ascii characters
|
|
|
|
std::wstring wprogram; |
|
|
|
std::wstring wprogram; |
|
|
|
if (!io::win32::strings::utf8_to_wcs(program.c_str(), &wprogram)) { |
|
|
|
if (!io::win32::strings::utf8_to_wcs(program.c_str(), &wprogram)) { |
|
|
|
GOOGLE_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'.
|
|
|
|
// Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'.
|
|
|
@ -128,7 +129,7 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { |
|
|
|
// get wide string version of command line as the path may contain non-ascii characters
|
|
|
|
// get wide string version of command line as the path may contain non-ascii characters
|
|
|
|
std::wstring wcommand_line; |
|
|
|
std::wstring wcommand_line; |
|
|
|
if (!io::win32::strings::utf8_to_wcs(command_line.c_str(), &wcommand_line)) { |
|
|
|
if (!io::win32::strings::utf8_to_wcs(command_line.c_str(), &wcommand_line)) { |
|
|
|
GOOGLE_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Using a malloc'ed string because CreateProcess() can mutate its second
|
|
|
|
// Using a malloc'ed string because CreateProcess() can mutate its second
|
|
|
@ -169,7 +170,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
GOOGLE_CHECK(child_handle_ != nullptr) << "Must call Start() first."; |
|
|
|
GOOGLE_ABSL_CHECK(child_handle_ != nullptr) << "Must call Start() first."; |
|
|
|
|
|
|
|
|
|
|
|
std::string input_data; |
|
|
|
std::string input_data; |
|
|
|
if (!input.SerializeToString(&input_data)) { |
|
|
|
if (!input.SerializeToString(&input_data)) { |
|
|
@ -199,11 +200,11 @@ bool Subprocess::Communicate(const Message& input, Message* output, |
|
|
|
wait_result < WAIT_OBJECT_0 + handle_count) { |
|
|
|
wait_result < WAIT_OBJECT_0 + handle_count) { |
|
|
|
signaled_handle = handles[wait_result - WAIT_OBJECT_0]; |
|
|
|
signaled_handle = handles[wait_result - WAIT_OBJECT_0]; |
|
|
|
} else if (wait_result == WAIT_FAILED) { |
|
|
|
} else if (wait_result == WAIT_FAILED) { |
|
|
|
GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "WaitForMultipleObjects: " |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: " |
|
|
|
<< wait_result; |
|
|
|
<< wait_result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (signaled_handle == child_stdin_) { |
|
|
|
if (signaled_handle == child_stdin_) { |
|
|
@ -246,17 +247,17 @@ bool Subprocess::Communicate(const Message& input, Message* output, |
|
|
|
DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE); |
|
|
|
DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE); |
|
|
|
|
|
|
|
|
|
|
|
if (wait_result == WAIT_FAILED) { |
|
|
|
if (wait_result == WAIT_FAILED) { |
|
|
|
GOOGLE_LOG(FATAL) << "WaitForSingleObject: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "WaitForSingleObject: " |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
} else if (wait_result != WAIT_OBJECT_0) { |
|
|
|
} else if (wait_result != WAIT_OBJECT_0) { |
|
|
|
GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: " |
|
|
|
<< wait_result; |
|
|
|
<< wait_result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DWORD exit_code; |
|
|
|
DWORD exit_code; |
|
|
|
if (!GetExitCodeProcess(child_handle_, &exit_code)) { |
|
|
|
if (!GetExitCodeProcess(child_handle_, &exit_code)) { |
|
|
|
GOOGLE_LOG(FATAL) << "GetExitCodeProcess: " |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "GetExitCodeProcess: " |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
<< Win32ErrorMessage(GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CloseHandleOrDie(child_handle_); |
|
|
|
CloseHandleOrDie(child_handle_); |
|
|
@ -325,14 +326,14 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { |
|
|
|
int stdin_pipe[2]; |
|
|
|
int stdin_pipe[2]; |
|
|
|
int stdout_pipe[2]; |
|
|
|
int stdout_pipe[2]; |
|
|
|
|
|
|
|
|
|
|
|
GOOGLE_CHECK(pipe(stdin_pipe) != -1); |
|
|
|
GOOGLE_ABSL_CHECK(pipe(stdin_pipe) != -1); |
|
|
|
GOOGLE_CHECK(pipe(stdout_pipe) != -1); |
|
|
|
GOOGLE_ABSL_CHECK(pipe(stdout_pipe) != -1); |
|
|
|
|
|
|
|
|
|
|
|
char* argv[2] = {portable_strdup(program.c_str()), nullptr}; |
|
|
|
char* argv[2] = {portable_strdup(program.c_str()), nullptr}; |
|
|
|
|
|
|
|
|
|
|
|
child_pid_ = fork(); |
|
|
|
child_pid_ = fork(); |
|
|
|
if (child_pid_ == -1) { |
|
|
|
if (child_pid_ == -1) { |
|
|
|
GOOGLE_LOG(FATAL) << "fork: " << strerror(errno); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "fork: " << strerror(errno); |
|
|
|
} else if (child_pid_ == 0) { |
|
|
|
} else if (child_pid_ == 0) { |
|
|
|
// We are the child.
|
|
|
|
// We are the child.
|
|
|
|
dup2(stdin_pipe[0], STDIN_FILENO); |
|
|
|
dup2(stdin_pipe[0], STDIN_FILENO); |
|
|
@ -379,7 +380,7 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { |
|
|
|
|
|
|
|
|
|
|
|
bool Subprocess::Communicate(const Message& input, Message* output, |
|
|
|
bool Subprocess::Communicate(const Message& input, Message* output, |
|
|
|
std::string* error) { |
|
|
|
std::string* error) { |
|
|
|
GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; |
|
|
|
GOOGLE_ABSL_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; |
|
|
|
|
|
|
|
|
|
|
|
// The "sighandler_t" typedef is GNU-specific, so define our own.
|
|
|
|
// The "sighandler_t" typedef is GNU-specific, so define our own.
|
|
|
|
typedef void SignalHandler(int); |
|
|
|
typedef void SignalHandler(int); |
|
|
@ -414,7 +415,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, |
|
|
|
// Interrupted by signal. Try again.
|
|
|
|
// Interrupted by signal. Try again.
|
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
GOOGLE_LOG(FATAL) << "select: " << strerror(errno); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "select: " << strerror(errno); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -460,7 +461,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, |
|
|
|
int status; |
|
|
|
int status; |
|
|
|
while (waitpid(child_pid_, &status, 0) == -1) { |
|
|
|
while (waitpid(child_pid_, &status, 0) == -1) { |
|
|
|
if (errno != EINTR) { |
|
|
|
if (errno != EINTR) { |
|
|
|
GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno); |
|
|
|
GOOGLE_ABSL_LOG(FATAL) << "waitpid: " << strerror(errno); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|