1d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Protocol Buffers - Google's data interchange format 2d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Copyright 2008 Google Inc. All rights reserved. 3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson// https://developers.google.com/protocol-buffers/ 4d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// 5d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Redistribution and use in source and binary forms, with or without 6d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// modification, are permitted provided that the following conditions are 7d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// met: 8d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// 9d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// * Redistributions of source code must retain the above copyright 10d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// notice, this list of conditions and the following disclaimer. 11d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// * Redistributions in binary form must reproduce the above 12d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// copyright notice, this list of conditions and the following disclaimer 13d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// in the documentation and/or other materials provided with the 14d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// distribution. 15d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// * Neither the name of Google Inc. nor the names of its 16d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// contributors may be used to endorse or promote products derived from 17d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// this software without specific prior written permission. 18d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// 19d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 31d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Author: kenton@google.com (Kenton Varda) 32d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 33d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/subprocess.h> 34d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 35a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson#include <algorithm> 36a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson#include <iostream> 37a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 38d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifndef _WIN32 39d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <errno.h> 40a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson#include <sys/select.h> 41d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <sys/wait.h> 42d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <signal.h> 43d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif 44d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/stubs/logging.h> 46d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/common.h> 47d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/message.h> 48d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/substitute.h> 49d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 51d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace google { 52d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace protobuf { 53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace compiler { 54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifdef _WIN32 56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 57d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestatic void CloseHandleOrDie(HANDLE handle) { 58d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!CloseHandle(handle)) { 59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "CloseHandle: " 60d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << Subprocess::Win32ErrorMessage(GetLastError()); 61d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 62d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 63d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 64d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::Subprocess() 65d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville : process_start_error_(ERROR_SUCCESS), 66d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_handle_(NULL), child_stdin_(NULL), child_stdout_(NULL) {} 67d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 68d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::~Subprocess() { 69d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdin_ != NULL) { 70d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(child_stdin_); 71d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 72d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdout_ != NULL) { 73d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(child_stdout_); 74d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 75d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 76d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 77d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid Subprocess::Start(const string& program, SearchMode search_mode) { 78d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Create the pipes. 79d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HANDLE stdin_pipe_read; 80d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HANDLE stdin_pipe_write; 81d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HANDLE stdout_pipe_read; 82d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HANDLE stdout_pipe_write; 83d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 84d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, NULL, 0)) { 85d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); 86d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 87d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, NULL, 0)) { 88d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); 89d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 90d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 91d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Make child side of the pipes inheritable. 92d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!SetHandleInformation(stdin_pipe_read, 93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { 94d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "SetHandleInformation: " 95d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << Win32ErrorMessage(GetLastError()); 96d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 97d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!SetHandleInformation(stdout_pipe_write, 98d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { 99d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "SetHandleInformation: " 100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << Win32ErrorMessage(GetLastError()); 101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Setup STARTUPINFO to redirect handles. 104a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson STARTUPINFOA startup_info; 105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ZeroMemory(&startup_info, sizeof(startup_info)); 106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville startup_info.cb = sizeof(startup_info); 107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville startup_info.dwFlags = STARTF_USESTDHANDLES; 108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville startup_info.hStdInput = stdin_pipe_read; 109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville startup_info.hStdOutput = stdout_pipe_write; 110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); 111d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 112d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (startup_info.hStdError == INVALID_HANDLE_VALUE) { 113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "GetStdHandle: " 114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << Win32ErrorMessage(GetLastError()); 115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // CreateProcess() mutates its second parameter. WTF? 118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville char* name_copy = strdup(program.c_str()); 119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Create the process. 121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville PROCESS_INFORMATION process_info; 122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 123a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(), 124a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson (search_mode == SEARCH_PATH) ? name_copy : NULL, 125a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson NULL, // process security attributes 126a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson NULL, // thread security attributes 127a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson TRUE, // inherit handles? 128a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 0, // obscure creation flags 129a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson NULL, // environment (inherit from parent) 130a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson NULL, // current directory (inherit from parent) 131a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson &startup_info, 132a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson &process_info)) { 133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_handle_ = process_info.hProcess; 134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(process_info.hThread); 135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdin_ = stdin_pipe_write; 136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdout_ = stdout_pipe_read; 137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville process_start_error_ = GetLastError(); 139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(stdin_pipe_write); 140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(stdout_pipe_read); 141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(stdin_pipe_read); 144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(stdout_pipe_write); 145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville free(name_copy); 146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool Subprocess::Communicate(const Message& input, Message* output, 149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string* error) { 150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (process_start_error_ != ERROR_SUCCESS) { 151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = Win32ErrorMessage(process_start_error_); 152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first."; 156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string input_data = input.SerializeAsString(); 158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string output_data; 159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int input_pos = 0; 161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville while (child_stdout_ != NULL) { 163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HANDLE handles[2]; 164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int handle_count = 0; 165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdin_ != NULL) { 167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville handles[handle_count++] = child_stdin_; 168d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 169d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdout_ != NULL) { 170d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville handles[handle_count++] = child_stdout_; 171d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville DWORD wait_result = 174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE); 175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer HANDLE signaled_handle = NULL; 177d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (wait_result >= WAIT_OBJECT_0 && 178d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville wait_result < WAIT_OBJECT_0 + handle_count) { 179d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville signaled_handle = handles[wait_result - WAIT_OBJECT_0]; 180d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (wait_result == WAIT_FAILED) { 181d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: " 182d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << Win32ErrorMessage(GetLastError()); 183d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 184d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: " 185d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << wait_result; 186d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 187d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 188d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (signaled_handle == child_stdin_) { 189d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville DWORD n; 190d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!WriteFile(child_stdin_, 191d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville input_data.data() + input_pos, 192d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville input_data.size() - input_pos, 193d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville &n, NULL)) { 194d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Child closed pipe. Presumably it will report an error later. 195d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Pretend we're done for now. 196d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville input_pos = input_data.size(); 197d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 198d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville input_pos += n; 199d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 200d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 201d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (input_pos == input_data.size()) { 202d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We're done writing. Close. 203d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(child_stdin_); 204d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdin_ = NULL; 205d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 206d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (signaled_handle == child_stdout_) { 207d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville char buffer[4096]; 208d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville DWORD n; 209d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 210d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!ReadFile(child_stdout_, buffer, sizeof(buffer), &n, NULL)) { 211d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We're done reading. Close. 212d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(child_stdout_); 213d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdout_ = NULL; 214d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 215d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville output_data.append(buffer, n); 216d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 217d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 218d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 219d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 220d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdin_ != NULL) { 221d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Child did not finish reading input before it closed the output. 222d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Presumably it exited with an error. 223d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(child_stdin_); 224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdin_ = NULL; 225d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 226d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 227d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE); 228d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 229d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (wait_result == WAIT_FAILED) { 230d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "WaitForSingleObject: " 231d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << Win32ErrorMessage(GetLastError()); 232d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (wait_result != WAIT_OBJECT_0) { 233d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: " 234d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << wait_result; 235d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 236d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 237d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville DWORD exit_code; 238d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!GetExitCodeProcess(child_handle_, &exit_code)) { 239d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "GetExitCodeProcess: " 240d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << Win32ErrorMessage(GetLastError()); 241d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 242d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 243d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CloseHandleOrDie(child_handle_); 244d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_handle_ = NULL; 245d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 246d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (exit_code != 0) { 247d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = strings::Substitute( 248d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "Plugin failed with status code $0.", exit_code); 249d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 250d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 251d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 252d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!output->ParseFromString(output_data)) { 253d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = "Plugin output is unparseable: " + CEscape(output_data); 254d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 255d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 256d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 257d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return true; 258d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 259d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 260d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestring Subprocess::Win32ErrorMessage(DWORD error_code) { 261d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville char* message; 262d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 263d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // WTF? 264d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 265d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FORMAT_MESSAGE_FROM_SYSTEM | 266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FORMAT_MESSAGE_IGNORE_INSERTS, 267d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville NULL, error_code, 0, 268d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville (LPTSTR)&message, // NOT A BUG! 269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 0, NULL); 270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 271d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string result = message; 272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville LocalFree(message); 273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return result; 274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// =================================================================== 277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 278d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#else // _WIN32 279d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 280d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::Subprocess() 281d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {} 282d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSubprocess::~Subprocess() { 284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdin_ != -1) { 285d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(child_stdin_); 286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdout_ != -1) { 288d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(child_stdout_); 289d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 290d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 291d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 292d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid Subprocess::Start(const string& program, SearchMode search_mode) { 293d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Note that we assume that there are no other threads, thus we don't have to 294d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // do crazy stuff like using socket pairs or avoiding libc locks. 295d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 296d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // [0] is read end, [1] is write end. 297d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int stdin_pipe[2]; 298d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int stdout_pipe[2]; 299d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 300a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson GOOGLE_CHECK(pipe(stdin_pipe) != -1); 301a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson GOOGLE_CHECK(pipe(stdout_pipe) != -1); 302d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 303d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville char* argv[2] = { strdup(program.c_str()), NULL }; 304d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 305d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_pid_ = fork(); 306d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_pid_ == -1) { 307d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "fork: " << strerror(errno); 308d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (child_pid_ == 0) { 309d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We are the child. 310d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville dup2(stdin_pipe[0], STDIN_FILENO); 311d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville dup2(stdout_pipe[1], STDOUT_FILENO); 312d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 313d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(stdin_pipe[0]); 314d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(stdin_pipe[1]); 315d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(stdout_pipe[0]); 316d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(stdout_pipe[1]); 317d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 318d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville switch (search_mode) { 319d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville case SEARCH_PATH: 320d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville execvp(argv[0], argv); 321d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville break; 322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville case EXACT_NAME: 323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville execv(argv[0], argv); 324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville break; 325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 326d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 327d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Write directly to STDERR_FILENO to avoid stdio code paths that may do 328d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // stuff that is unsafe here. 329a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson int ignored; 330a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ignored = write(STDERR_FILENO, argv[0], strlen(argv[0])); 331d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const char* message = ": program not found or is not executable\n"; 332a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ignored = write(STDERR_FILENO, message, strlen(message)); 333a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson (void) ignored; 334d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 335d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Must use _exit() rather than exit() to avoid flushing output buffers 336d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // that will also be flushed by the parent. 337d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville _exit(1); 338d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 339d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville free(argv[0]); 340d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 341d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(stdin_pipe[0]); 342d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(stdout_pipe[1]); 343d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 344d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdin_ = stdin_pipe[1]; 345d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdout_ = stdout_pipe[0]; 346d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 347d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 348d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 349d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool Subprocess::Communicate(const Message& input, Message* output, 350d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string* error) { 351d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 352d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; 353d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // The "sighandler_t" typedef is GNU-specific, so define our own. 355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville typedef void SignalHandler(int); 356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 357d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us. 358d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN); 359d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 360d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string input_data = input.SerializeAsString(); 361d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string output_data; 362d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 363d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int input_pos = 0; 364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int max_fd = std::max(child_stdin_, child_stdout_); 365d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 366d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville while (child_stdout_ != -1) { 367d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville fd_set read_fds; 368d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville fd_set write_fds; 369d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FD_ZERO(&read_fds); 370d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FD_ZERO(&write_fds); 371d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdout_ != -1) { 372d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FD_SET(child_stdout_, &read_fds); 373d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 374d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdin_ != -1) { 375d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville FD_SET(child_stdin_, &write_fds); 376d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 377d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 378d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) { 379d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (errno == EINTR) { 380d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Interrupted by signal. Try again. 381d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville continue; 382d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 383d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "select: " << strerror(errno); 384d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 385d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 386d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 387d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) { 388d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int n = write(child_stdin_, input_data.data() + input_pos, 389d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville input_data.size() - input_pos); 390d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (n < 0) { 391d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Child closed pipe. Presumably it will report an error later. 392d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Pretend we're done for now. 393d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville input_pos = input_data.size(); 394d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 395d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville input_pos += n; 396d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 397d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 398d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (input_pos == input_data.size()) { 399d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We're done writing. Close. 400d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(child_stdin_); 401d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdin_ = -1; 402d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 403d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 404d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 405d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) { 406d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville char buffer[4096]; 407d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int n = read(child_stdout_, buffer, sizeof(buffer)); 408d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 409d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (n > 0) { 410d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville output_data.append(buffer, n); 411d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 412d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We're done reading. Close. 413d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(child_stdout_); 414d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdout_ = -1; 415d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 416d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 417d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 418d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 419d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (child_stdin_ != -1) { 420d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Child did not finish reading input before it closed the output. 421d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Presumably it exited with an error. 422d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville close(child_stdin_); 423d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville child_stdin_ = -1; 424d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 425d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 426d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int status; 427d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville while (waitpid(child_pid_, &status, 0) == -1) { 428d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (errno != EINTR) { 429d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno); 430d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 431d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 432d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 433d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Restore SIGPIPE handling. 434d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville signal(SIGPIPE, old_pipe_handler); 435d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 436d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (WIFEXITED(status)) { 437d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (WEXITSTATUS(status) != 0) { 438d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int error_code = WEXITSTATUS(status); 439d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = strings::Substitute( 440d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "Plugin failed with status code $0.", error_code); 441d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 442d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 443d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (WIFSIGNALED(status)) { 444d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int signal = WTERMSIG(status); 445d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = strings::Substitute( 446d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "Plugin killed by signal $0.", signal); 447d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 448d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 449d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = "Neither WEXITSTATUS nor WTERMSIG is true?"; 450d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 451d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 452d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 453d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!output->ParseFromString(output_data)) { 454a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson *error = "Plugin output is unparseable: " + CEscape(output_data); 455d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 456d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 457d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 458d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return true; 459d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 460d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 461d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif // !_WIN32 462d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 463d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} // namespace compiler 464d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} // namespace protobuf 465d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} // namespace google 466