诸暨麻将添加redis
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

477 righe
15 KiB

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