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