subprocess.cc 14 KB

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