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