diff options
Diffstat (limited to 'third_party/protobuf/src/google/protobuf/compiler/subprocess.cc')
-rw-r--r-- | third_party/protobuf/src/google/protobuf/compiler/subprocess.cc | 465 |
1 files changed, 0 insertions, 465 deletions
diff --git a/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc b/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc deleted file mode 100644 index a30ac30519..0000000000 --- a/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc +++ /dev/null @@ -1,465 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) - -#include <google/protobuf/compiler/subprocess.h> - -#include <algorithm> -#include <iostream> - -#ifndef _WIN32 -#include <errno.h> -#include <sys/select.h> -#include <sys/wait.h> -#include <signal.h> -#endif - -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/message.h> -#include <google/protobuf/stubs/substitute.h> - - -namespace google { -namespace protobuf { -namespace compiler { - -#ifdef _WIN32 - -static void CloseHandleOrDie(HANDLE handle) { - if (!CloseHandle(handle)) { - GOOGLE_LOG(FATAL) << "CloseHandle: " - << Subprocess::Win32ErrorMessage(GetLastError()); - } -} - -Subprocess::Subprocess() - : process_start_error_(ERROR_SUCCESS), - child_handle_(NULL), child_stdin_(NULL), child_stdout_(NULL) {} - -Subprocess::~Subprocess() { - if (child_stdin_ != NULL) { - CloseHandleOrDie(child_stdin_); - } - if (child_stdout_ != NULL) { - CloseHandleOrDie(child_stdout_); - } -} - -void Subprocess::Start(const string& program, SearchMode search_mode) { - // Create the pipes. - HANDLE stdin_pipe_read; - HANDLE stdin_pipe_write; - HANDLE stdout_pipe_read; - HANDLE stdout_pipe_write; - - if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, NULL, 0)) { - GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); - } - if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, NULL, 0)) { - GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); - } - - // Make child side of the pipes inheritable. - if (!SetHandleInformation(stdin_pipe_read, - HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { - GOOGLE_LOG(FATAL) << "SetHandleInformation: " - << Win32ErrorMessage(GetLastError()); - } - if (!SetHandleInformation(stdout_pipe_write, - HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { - GOOGLE_LOG(FATAL) << "SetHandleInformation: " - << Win32ErrorMessage(GetLastError()); - } - - // Setup STARTUPINFO to redirect handles. - STARTUPINFOA startup_info; - ZeroMemory(&startup_info, sizeof(startup_info)); - startup_info.cb = sizeof(startup_info); - startup_info.dwFlags = STARTF_USESTDHANDLES; - startup_info.hStdInput = stdin_pipe_read; - startup_info.hStdOutput = stdout_pipe_write; - startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); - - if (startup_info.hStdError == INVALID_HANDLE_VALUE) { - GOOGLE_LOG(FATAL) << "GetStdHandle: " - << Win32ErrorMessage(GetLastError()); - } - - // CreateProcess() mutates its second parameter. WTF? - char* name_copy = strdup(program.c_str()); - - // Create the process. - PROCESS_INFORMATION process_info; - - if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(), - (search_mode == SEARCH_PATH) ? name_copy : NULL, - NULL, // process security attributes - NULL, // thread security attributes - TRUE, // inherit handles? - 0, // obscure creation flags - NULL, // environment (inherit from parent) - NULL, // current directory (inherit from parent) - &startup_info, - &process_info)) { - child_handle_ = process_info.hProcess; - CloseHandleOrDie(process_info.hThread); - child_stdin_ = stdin_pipe_write; - child_stdout_ = stdout_pipe_read; - } else { - process_start_error_ = GetLastError(); - CloseHandleOrDie(stdin_pipe_write); - CloseHandleOrDie(stdout_pipe_read); - } - - CloseHandleOrDie(stdin_pipe_read); - CloseHandleOrDie(stdout_pipe_write); - free(name_copy); -} - -bool Subprocess::Communicate(const Message& input, Message* output, - string* error) { - if (process_start_error_ != ERROR_SUCCESS) { - *error = Win32ErrorMessage(process_start_error_); - return false; - } - - GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first."; - - string input_data = input.SerializeAsString(); - string output_data; - - int input_pos = 0; - - while (child_stdout_ != NULL) { - HANDLE handles[2]; - int handle_count = 0; - - if (child_stdin_ != NULL) { - handles[handle_count++] = child_stdin_; - } - if (child_stdout_ != NULL) { - handles[handle_count++] = child_stdout_; - } - - DWORD wait_result = - WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE); - - HANDLE signaled_handle = NULL; - if (wait_result >= WAIT_OBJECT_0 && - wait_result < WAIT_OBJECT_0 + handle_count) { - signaled_handle = handles[wait_result - WAIT_OBJECT_0]; - } else if (wait_result == WAIT_FAILED) { - GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: " - << Win32ErrorMessage(GetLastError()); - } else { - GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: " - << wait_result; - } - - if (signaled_handle == child_stdin_) { - DWORD n; - if (!WriteFile(child_stdin_, - input_data.data() + input_pos, - input_data.size() - input_pos, - &n, NULL)) { - // Child closed pipe. Presumably it will report an error later. - // Pretend we're done for now. - input_pos = input_data.size(); - } else { - input_pos += n; - } - - if (input_pos == input_data.size()) { - // We're done writing. Close. - CloseHandleOrDie(child_stdin_); - child_stdin_ = NULL; - } - } else if (signaled_handle == child_stdout_) { - char buffer[4096]; - DWORD n; - - if (!ReadFile(child_stdout_, buffer, sizeof(buffer), &n, NULL)) { - // We're done reading. Close. - CloseHandleOrDie(child_stdout_); - child_stdout_ = NULL; - } else { - output_data.append(buffer, n); - } - } - } - - if (child_stdin_ != NULL) { - // Child did not finish reading input before it closed the output. - // Presumably it exited with an error. - CloseHandleOrDie(child_stdin_); - child_stdin_ = NULL; - } - - DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE); - - if (wait_result == WAIT_FAILED) { - GOOGLE_LOG(FATAL) << "WaitForSingleObject: " - << Win32ErrorMessage(GetLastError()); - } else if (wait_result != WAIT_OBJECT_0) { - GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: " - << wait_result; - } - - DWORD exit_code; - if (!GetExitCodeProcess(child_handle_, &exit_code)) { - GOOGLE_LOG(FATAL) << "GetExitCodeProcess: " - << Win32ErrorMessage(GetLastError()); - } - - CloseHandleOrDie(child_handle_); - child_handle_ = NULL; - - if (exit_code != 0) { - *error = strings::Substitute( - "Plugin failed with status code $0.", exit_code); - return false; - } - - if (!output->ParseFromString(output_data)) { - *error = "Plugin output is unparseable: " + CEscape(output_data); - return false; - } - - return true; -} - -string Subprocess::Win32ErrorMessage(DWORD error_code) { - char* message; - - // WTF? - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, 0, - (LPTSTR)&message, // NOT A BUG! - 0, NULL); - - string result = message; - LocalFree(message); - return result; -} - -// =================================================================== - -#else // _WIN32 - -Subprocess::Subprocess() - : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {} - -Subprocess::~Subprocess() { - if (child_stdin_ != -1) { - close(child_stdin_); - } - if (child_stdout_ != -1) { - close(child_stdout_); - } -} - -void Subprocess::Start(const string& program, SearchMode search_mode) { - // Note that we assume that there are no other threads, thus we don't have to - // do crazy stuff like using socket pairs or avoiding libc locks. - - // [0] is read end, [1] is write end. - int stdin_pipe[2]; - int stdout_pipe[2]; - - GOOGLE_CHECK(pipe(stdin_pipe) != -1); - GOOGLE_CHECK(pipe(stdout_pipe) != -1); - - char* argv[2] = { strdup(program.c_str()), NULL }; - - child_pid_ = fork(); - if (child_pid_ == -1) { - GOOGLE_LOG(FATAL) << "fork: " << strerror(errno); - } else if (child_pid_ == 0) { - // We are the child. - dup2(stdin_pipe[0], STDIN_FILENO); - dup2(stdout_pipe[1], STDOUT_FILENO); - - close(stdin_pipe[0]); - close(stdin_pipe[1]); - close(stdout_pipe[0]); - close(stdout_pipe[1]); - - switch (search_mode) { - case SEARCH_PATH: - execvp(argv[0], argv); - break; - case EXACT_NAME: - execv(argv[0], argv); - break; - } - - // Write directly to STDERR_FILENO to avoid stdio code paths that may do - // stuff that is unsafe here. - int ignored; - ignored = write(STDERR_FILENO, argv[0], strlen(argv[0])); - const char* message = ": program not found or is not executable\n"; - ignored = write(STDERR_FILENO, message, strlen(message)); - (void) ignored; - - // Must use _exit() rather than exit() to avoid flushing output buffers - // that will also be flushed by the parent. - _exit(1); - } else { - free(argv[0]); - - close(stdin_pipe[0]); - close(stdout_pipe[1]); - - child_stdin_ = stdin_pipe[1]; - child_stdout_ = stdout_pipe[0]; - } -} - -bool Subprocess::Communicate(const Message& input, Message* output, - string* error) { - - GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; - - // The "sighandler_t" typedef is GNU-specific, so define our own. - typedef void SignalHandler(int); - - // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us. - SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN); - - string input_data = input.SerializeAsString(); - string output_data; - - int input_pos = 0; - int max_fd = max(child_stdin_, child_stdout_); - - while (child_stdout_ != -1) { - fd_set read_fds; - fd_set write_fds; - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - if (child_stdout_ != -1) { - FD_SET(child_stdout_, &read_fds); - } - if (child_stdin_ != -1) { - FD_SET(child_stdin_, &write_fds); - } - - if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) { - if (errno == EINTR) { - // Interrupted by signal. Try again. - continue; - } else { - GOOGLE_LOG(FATAL) << "select: " << strerror(errno); - } - } - - if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) { - int n = write(child_stdin_, input_data.data() + input_pos, - input_data.size() - input_pos); - if (n < 0) { - // Child closed pipe. Presumably it will report an error later. - // Pretend we're done for now. - input_pos = input_data.size(); - } else { - input_pos += n; - } - - if (input_pos == input_data.size()) { - // We're done writing. Close. - close(child_stdin_); - child_stdin_ = -1; - } - } - - if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) { - char buffer[4096]; - int n = read(child_stdout_, buffer, sizeof(buffer)); - - if (n > 0) { - output_data.append(buffer, n); - } else { - // We're done reading. Close. - close(child_stdout_); - child_stdout_ = -1; - } - } - } - - if (child_stdin_ != -1) { - // Child did not finish reading input before it closed the output. - // Presumably it exited with an error. - close(child_stdin_); - child_stdin_ = -1; - } - - int status; - while (waitpid(child_pid_, &status, 0) == -1) { - if (errno != EINTR) { - GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno); - } - } - - // Restore SIGPIPE handling. - signal(SIGPIPE, old_pipe_handler); - - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) { - int error_code = WEXITSTATUS(status); - *error = strings::Substitute( - "Plugin failed with status code $0.", error_code); - return false; - } - } else if (WIFSIGNALED(status)) { - int signal = WTERMSIG(status); - *error = strings::Substitute( - "Plugin killed by signal $0.", signal); - return false; - } else { - *error = "Neither WEXITSTATUS nor WTERMSIG is true?"; - return false; - } - - if (!output->ParseFromString(output_data)) { - *error = "Plugin output is unparseable: " + CEscape(output_data); - return false; - } - - return true; -} - -#endif // !_WIN32 - -} // namespace compiler -} // namespace protobuf -} // namespace google |