OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_ANDROID) | 6 #if defined(TARGET_OS_ANDROID) |
7 | 7 |
8 #include "bin/process.h" | 8 #include "bin/process.h" |
9 | 9 |
10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
11 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
12 #include <poll.h> // NOLINT | 12 #include <poll.h> // NOLINT |
13 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
14 #include <stdlib.h> // NOLINT | 14 #include <stdlib.h> // NOLINT |
15 #include <string.h> // NOLINT | 15 #include <string.h> // NOLINT |
16 #include <sys/wait.h> // NOLINT | 16 #include <sys/wait.h> // NOLINT |
17 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
18 | 18 |
19 #include "bin/dartutils.h" | 19 #include "bin/dartutils.h" |
20 #include "bin/fdutils.h" | 20 #include "bin/fdutils.h" |
21 #include "bin/lockers.h" | 21 #include "bin/lockers.h" |
22 #include "bin/log.h" | 22 #include "bin/log.h" |
23 #include "bin/thread.h" | 23 #include "bin/thread.h" |
24 | 24 |
25 #include "platform/signal_blocker.h" | 25 #include "platform/signal_blocker.h" |
26 #include "platform/utils.h" | 26 #include "platform/utils.h" |
27 | 27 |
28 | |
29 extern char **environ; | 28 extern char **environ; |
30 | 29 |
31 | |
32 namespace dart { | 30 namespace dart { |
33 namespace bin { | 31 namespace bin { |
34 | 32 |
35 // ProcessInfo is used to map a process id to the file descriptor for | 33 // ProcessInfo is used to map a process id to the file descriptor for |
36 // the pipe used to communicate the exit code of the process to Dart. | 34 // the pipe used to communicate the exit code of the process to Dart. |
37 // ProcessInfo objects are kept in the static singly-linked | 35 // ProcessInfo objects are kept in the static singly-linked |
38 // ProcessInfoList. | 36 // ProcessInfoList. |
39 class ProcessInfo { | 37 class ProcessInfo { |
40 public: | 38 public: |
41 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } | 39 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } |
42 ~ProcessInfo() { | 40 ~ProcessInfo() { |
43 int closed = TEMP_FAILURE_RETRY(close(fd_)); | 41 int closed = TEMP_FAILURE_RETRY(close(fd_)); |
44 if (closed != 0) { | 42 if (closed != 0) { |
45 FATAL("Failed to close process exit code pipe"); | 43 FATAL("Failed to close process exit code pipe"); |
46 } | 44 } |
47 } | 45 } |
48 pid_t pid() { return pid_; } | 46 pid_t pid() { return pid_; } |
49 intptr_t fd() { return fd_; } | 47 intptr_t fd() { return fd_; } |
50 ProcessInfo* next() { return next_; } | 48 ProcessInfo* next() { return next_; } |
51 void set_next(ProcessInfo* info) { next_ = info; } | 49 void set_next(ProcessInfo* info) { next_ = info; } |
52 | 50 |
53 private: | 51 private: |
54 pid_t pid_; | 52 pid_t pid_; |
55 intptr_t fd_; | 53 intptr_t fd_; |
56 ProcessInfo* next_; | 54 ProcessInfo* next_; |
55 | |
56 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); | |
57 }; | 57 }; |
58 | 58 |
59 | 59 |
60 // Singly-linked list of ProcessInfo objects for all active processes | 60 // Singly-linked list of ProcessInfo objects for all active processes |
61 // started from Dart. | 61 // started from Dart. |
62 class ProcessInfoList { | 62 class ProcessInfoList { |
63 public: | 63 public: |
64 static void AddProcess(pid_t pid, intptr_t fd) { | 64 static void AddProcess(pid_t pid, intptr_t fd) { |
65 MutexLocker locker(mutex_); | 65 MutexLocker locker(mutex_); |
66 ProcessInfo* info = new ProcessInfo(pid, fd); | 66 ProcessInfo* info = new ProcessInfo(pid, fd); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 } | 101 } |
102 } | 102 } |
103 | 103 |
104 private: | 104 private: |
105 // Linked list of ProcessInfo objects for all active processes | 105 // Linked list of ProcessInfo objects for all active processes |
106 // started from Dart code. | 106 // started from Dart code. |
107 static ProcessInfo* active_processes_; | 107 static ProcessInfo* active_processes_; |
108 // Mutex protecting all accesses to the linked list of active | 108 // Mutex protecting all accesses to the linked list of active |
109 // processes. | 109 // processes. |
110 static Mutex* mutex_; | 110 static Mutex* mutex_; |
111 | |
112 DISALLOW_ALLOCATION(); | |
113 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); | |
111 }; | 114 }; |
112 | 115 |
113 | 116 |
114 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 117 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
115 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 118 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
116 | 119 |
117 | 120 |
118 // The exit code handler sets up a separate thread which waits for child | 121 // The exit code handler sets up a separate thread which waits for child |
119 // processes to terminate. That separate thread can then get the exit code from | 122 // processes to terminate. That separate thread can then get the exit code from |
120 // processes that have exited and communicate it to Dart through the | 123 // processes that have exited and communicate it to Dart through the |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 | 171 |
169 private: | 172 private: |
170 // Entry point for the separate exit code handler thread started by | 173 // Entry point for the separate exit code handler thread started by |
171 // the ExitCodeHandler. | 174 // the ExitCodeHandler. |
172 static void ExitCodeHandlerEntry(uword param) { | 175 static void ExitCodeHandlerEntry(uword param) { |
173 pid_t pid = 0; | 176 pid_t pid = 0; |
174 int status = 0; | 177 int status = 0; |
175 while (true) { | 178 while (true) { |
176 { | 179 { |
177 MonitorLocker locker(monitor_); | 180 MonitorLocker locker(monitor_); |
178 while (running_ && process_count_ == 0) { | 181 while (running_ && (process_count_ == 0)) { |
179 monitor_->Wait(Monitor::kNoTimeout); | 182 monitor_->Wait(Monitor::kNoTimeout); |
180 } | 183 } |
181 if (!running_) { | 184 if (!running_) { |
182 terminate_done_ = true; | 185 terminate_done_ = true; |
183 monitor_->Notify(); | 186 monitor_->Notify(); |
184 return; | 187 return; |
185 } | 188 } |
186 } | 189 } |
187 | 190 |
188 if ((pid = TEMP_FAILURE_RETRY(wait(&status))) > 0) { | 191 if ((pid = TEMP_FAILURE_RETRY(wait(&status))) > 0) { |
189 int exit_code = 0; | 192 int exit_code = 0; |
190 int negative = 0; | 193 int negative = 0; |
191 if (WIFEXITED(status)) { | 194 if (WIFEXITED(status)) { |
192 exit_code = WEXITSTATUS(status); | 195 exit_code = WEXITSTATUS(status); |
193 } | 196 } |
194 if (WIFSIGNALED(status)) { | 197 if (WIFSIGNALED(status)) { |
195 exit_code = WTERMSIG(status); | 198 exit_code = WTERMSIG(status); |
196 negative = 1; | 199 negative = 1; |
197 } | 200 } |
198 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); | 201 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); |
199 if (exit_code_fd != 0) { | 202 if (exit_code_fd != 0) { |
200 int message[2] = { exit_code, negative }; | 203 int message[2] = { exit_code, negative }; |
201 ssize_t result = | 204 ssize_t result = |
202 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); | 205 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); |
203 // If the process has been closed, the read end of the exit | 206 // If the process has been closed, the read end of the exit |
204 // pipe has been closed. It is therefore not a problem that | 207 // pipe has been closed. It is therefore not a problem that |
205 // write fails with a broken pipe error. Other errors should | 208 // write fails with a broken pipe error. Other errors should |
206 // not happen. | 209 // not happen. |
207 if (result != -1 && result != sizeof(message)) { | 210 if ((result != -1) && (result != sizeof(message))) { |
208 FATAL("Failed to write entire process exit message"); | 211 FATAL("Failed to write entire process exit message"); |
209 } else if (result == -1 && errno != EPIPE) { | 212 } else if ((result == -1) && (errno != EPIPE)) { |
210 FATAL1("Failed to write exit code: %d", errno); | 213 FATAL1("Failed to write exit code: %d", errno); |
211 } | 214 } |
212 ProcessInfoList::RemoveProcess(pid); | 215 ProcessInfoList::RemoveProcess(pid); |
213 { | 216 { |
214 MonitorLocker locker(monitor_); | 217 MonitorLocker locker(monitor_); |
215 process_count_--; | 218 process_count_--; |
216 } | 219 } |
217 } | 220 } |
218 } | 221 } |
219 } | 222 } |
220 } | 223 } |
221 | 224 |
222 static bool terminate_done_; | 225 static bool terminate_done_; |
223 static int process_count_; | 226 static int process_count_; |
224 static bool running_; | 227 static bool running_; |
225 static Monitor* monitor_; | 228 static Monitor* monitor_; |
229 | |
230 DISALLOW_ALLOCATION(); | |
231 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); | |
226 }; | 232 }; |
227 | 233 |
228 | 234 |
229 bool ExitCodeHandler::running_ = false; | 235 bool ExitCodeHandler::running_ = false; |
230 int ExitCodeHandler::process_count_ = 0; | 236 int ExitCodeHandler::process_count_ = 0; |
231 bool ExitCodeHandler::terminate_done_ = false; | 237 bool ExitCodeHandler::terminate_done_ = false; |
232 Monitor* ExitCodeHandler::monitor_ = new Monitor(); | 238 Monitor* ExitCodeHandler::monitor_ = new Monitor(); |
233 | 239 |
234 | 240 |
235 class ProcessStarter { | 241 class ProcessStarter { |
(...skipping 22 matching lines...) Expand all Loading... | |
258 os_error_message_(os_error_message) { | 264 os_error_message_(os_error_message) { |
259 read_in_[0] = -1; | 265 read_in_[0] = -1; |
260 read_in_[1] = -1; | 266 read_in_[1] = -1; |
261 read_err_[0] = -1; | 267 read_err_[0] = -1; |
262 read_err_[1] = -1; | 268 read_err_[1] = -1; |
263 write_out_[0] = -1; | 269 write_out_[0] = -1; |
264 write_out_[1] = -1; | 270 write_out_[1] = -1; |
265 exec_control_[0] = -1; | 271 exec_control_[0] = -1; |
266 exec_control_[1] = -1; | 272 exec_control_[1] = -1; |
267 | 273 |
268 program_arguments_ = new char*[arguments_length + 2]; | 274 program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate( |
zra
2016/03/15 18:12:29
Made this scope allocated.
| |
275 (arguments_length + 2) * sizeof(*program_arguments_))); | |
269 program_arguments_[0] = const_cast<char*>(path_); | 276 program_arguments_[0] = const_cast<char*>(path_); |
270 for (int i = 0; i < arguments_length; i++) { | 277 for (int i = 0; i < arguments_length; i++) { |
271 program_arguments_[i + 1] = arguments[i]; | 278 program_arguments_[i + 1] = arguments[i]; |
272 } | 279 } |
273 program_arguments_[arguments_length + 1] = NULL; | 280 program_arguments_[arguments_length + 1] = NULL; |
274 | 281 |
275 program_environment_ = NULL; | 282 program_environment_ = NULL; |
276 if (environment != NULL) { | 283 if (environment != NULL) { |
277 program_environment_ = new char*[environment_length + 1]; | 284 program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate( |
zra
2016/03/15 18:12:29
ditto.
| |
285 (environment_length + 1) * sizeof(*program_environment_))); | |
278 for (int i = 0; i < environment_length; i++) { | 286 for (int i = 0; i < environment_length; i++) { |
279 program_environment_[i] = environment[i]; | 287 program_environment_[i] = environment[i]; |
280 } | 288 } |
281 program_environment_[environment_length] = NULL; | 289 program_environment_[environment_length] = NULL; |
282 } | 290 } |
283 } | 291 } |
284 | 292 |
285 | 293 |
286 ~ProcessStarter() { | |
287 delete[] program_arguments_; | |
288 delete[] program_environment_; | |
289 } | |
290 | |
291 | |
292 int Start() { | 294 int Start() { |
293 // Create pipes required. | 295 // Create pipes required. |
294 int err = CreatePipes(); | 296 int err = CreatePipes(); |
295 if (err != 0) return err; | 297 if (err != 0) { |
298 return err; | |
299 } | |
296 | 300 |
297 // Fork to create the new process. | 301 // Fork to create the new process. |
298 pid_t pid = TEMP_FAILURE_RETRY(fork()); | 302 pid_t pid = TEMP_FAILURE_RETRY(fork()); |
299 if (pid < 0) { | 303 if (pid < 0) { |
300 // Failed to fork. | 304 // Failed to fork. |
301 return CleanupAndReturnError(); | 305 return CleanupAndReturnError(); |
302 } else if (pid == 0) { | 306 } else if (pid == 0) { |
303 // This runs in the new process. | 307 // This runs in the new process. |
304 NewProcess(); | 308 NewProcess(); |
305 } | 309 } |
306 | 310 |
307 // This runs in the original process. | 311 // This runs in the original process. |
308 | 312 |
309 // Be sure to listen for exit-codes, now we have a child-process. | 313 // Be sure to listen for exit-codes, now we have a child-process. |
310 ExitCodeHandler::ProcessStarted(); | 314 ExitCodeHandler::ProcessStarted(); |
311 | 315 |
312 // Register the child process if not detached. | 316 // Register the child process if not detached. |
313 if (mode_ == kNormal) { | 317 if (mode_ == kNormal) { |
314 err = RegisterProcess(pid); | 318 err = RegisterProcess(pid); |
315 if (err != 0) return err; | 319 if (err != 0) { |
320 return err; | |
321 } | |
316 } | 322 } |
317 | 323 |
318 // Notify child process to start. This is done to delay the call to exec | 324 // Notify child process to start. This is done to delay the call to exec |
319 // until the process is registered above, and we are ready to receive the | 325 // until the process is registered above, and we are ready to receive the |
320 // exit code. | 326 // exit code. |
321 char msg = '1'; | 327 char msg = '1'; |
322 int bytes_written = | 328 int bytes_written = |
323 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg)); | 329 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg)); |
324 if (bytes_written != sizeof(msg)) { | 330 if (bytes_written != sizeof(msg)) { |
325 return CleanupAndReturnError(); | 331 return CleanupAndReturnError(); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
484 pid = TEMP_FAILURE_RETRY(fork()); | 490 pid = TEMP_FAILURE_RETRY(fork()); |
485 if (pid < 0) { | 491 if (pid < 0) { |
486 ReportChildError(); | 492 ReportChildError(); |
487 } else if (pid == 0) { | 493 } else if (pid == 0) { |
488 if (mode_ == kDetached) { | 494 if (mode_ == kDetached) { |
489 SetupDetached(); | 495 SetupDetached(); |
490 } else { | 496 } else { |
491 SetupDetachedWithStdio(); | 497 SetupDetachedWithStdio(); |
492 } | 498 } |
493 | 499 |
494 if (working_directory_ != NULL && | 500 if ((working_directory_ != NULL) && |
495 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 501 (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) { |
496 ReportChildError(); | 502 ReportChildError(); |
497 } | 503 } |
498 | 504 |
499 // Report the final PID and do the exec. | 505 // Report the final PID and do the exec. |
500 ReportPid(getpid()); // getpid cannot fail. | 506 ReportPid(getpid()); // getpid cannot fail. |
501 VOID_TEMP_FAILURE_RETRY( | 507 VOID_TEMP_FAILURE_RETRY( |
502 execvp(path_, const_cast<char* const*>(program_arguments_))); | 508 execvp(path_, const_cast<char* const*>(program_arguments_))); |
503 ReportChildError(); | 509 ReportChildError(); |
504 } else { | 510 } else { |
505 // Exit the intermeiate process. | 511 // Exit the intermeiate process. |
(...skipping 21 matching lines...) Expand all Loading... | |
527 return 0; | 533 return 0; |
528 } | 534 } |
529 | 535 |
530 | 536 |
531 int ReadExecResult() { | 537 int ReadExecResult() { |
532 int child_errno; | 538 int child_errno; |
533 int bytes_read = -1; | 539 int bytes_read = -1; |
534 // Read exec result from child. If no data is returned the exec was | 540 // Read exec result from child. If no data is returned the exec was |
535 // successful and the exec call closed the pipe. Otherwise the errno | 541 // successful and the exec call closed the pipe. Otherwise the errno |
536 // is written to the pipe. | 542 // is written to the pipe. |
537 bytes_read = | 543 bytes_read = FDUtils::ReadFromBlocking( |
538 FDUtils::ReadFromBlocking( | 544 exec_control_[0], &child_errno, sizeof(child_errno)); |
539 exec_control_[0], &child_errno, sizeof(child_errno)); | |
540 if (bytes_read == sizeof(child_errno)) { | 545 if (bytes_read == sizeof(child_errno)) { |
541 ReadChildError(); | 546 ReadChildError(); |
542 return child_errno; | 547 return child_errno; |
543 } else if (bytes_read == -1) { | 548 } else if (bytes_read == -1) { |
544 return errno; | 549 return errno; |
545 } | 550 } |
546 return 0; | 551 return 0; |
547 } | 552 } |
548 | 553 |
549 | 554 |
550 int ReadDetachedExecResult(pid_t *pid) { | 555 int ReadDetachedExecResult(pid_t *pid) { |
551 int child_errno; | 556 int child_errno; |
552 int bytes_read = -1; | 557 int bytes_read = -1; |
553 // Read exec result from child. If only pid data is returned the exec was | 558 // Read exec result from child. If only pid data is returned the exec was |
554 // successful and the exec call closed the pipe. Otherwise the errno | 559 // successful and the exec call closed the pipe. Otherwise the errno |
555 // is written to the pipe as well. | 560 // is written to the pipe as well. |
556 int result[2]; | 561 int result[2]; |
557 bytes_read = | 562 bytes_read = |
558 FDUtils::ReadFromBlocking( | 563 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result)); |
559 exec_control_[0], result, sizeof(result)); | |
560 if (bytes_read == sizeof(int)) { | 564 if (bytes_read == sizeof(int)) { |
561 *pid = result[0]; | 565 *pid = result[0]; |
562 } else if (bytes_read == 2 * sizeof(int)) { | 566 } else if (bytes_read == 2 * sizeof(int)) { |
563 *pid = result[0]; | 567 *pid = result[0]; |
564 child_errno = result[1]; | 568 child_errno = result[1]; |
565 ReadChildError(); | 569 ReadChildError(); |
566 return child_errno; | 570 return child_errno; |
567 } else if (bytes_read == -1) { | 571 } else if (bytes_read == -1) { |
568 return errno; | 572 return errno; |
569 } | 573 } |
570 return 0; | 574 return 0; |
571 } | 575 } |
572 | 576 |
573 | 577 |
574 void SetupDetached() { | 578 void SetupDetached() { |
575 ASSERT(mode_ == kDetached); | 579 ASSERT(mode_ == kDetached); |
576 | 580 |
577 // Close all open file descriptors except for exec_control_[1]. | 581 // Close all open file descriptors except for exec_control_[1]. |
578 int max_fds = sysconf(_SC_OPEN_MAX); | 582 int max_fds = sysconf(_SC_OPEN_MAX); |
579 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; | 583 if (max_fds == -1) { |
584 max_fds = _POSIX_OPEN_MAX; | |
585 } | |
580 for (int fd = 0; fd < max_fds; fd++) { | 586 for (int fd = 0; fd < max_fds; fd++) { |
581 if (fd != exec_control_[1]) { | 587 if (fd != exec_control_[1]) { |
582 VOID_TEMP_FAILURE_RETRY(close(fd)); | 588 VOID_TEMP_FAILURE_RETRY(close(fd)); |
583 } | 589 } |
584 } | 590 } |
585 | 591 |
586 // Re-open stdin, stdout and stderr and connect them to /dev/null. | 592 // Re-open stdin, stdout and stderr and connect them to /dev/null. |
587 // The loop above should already have closed all of them, so | 593 // The loop above should already have closed all of them, so |
588 // creating new file descriptors should start at STDIN_FILENO. | 594 // creating new file descriptors should start at STDIN_FILENO. |
589 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); | 595 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); |
590 if (fd != STDIN_FILENO) { | 596 if (fd != STDIN_FILENO) { |
591 ReportChildError(); | 597 ReportChildError(); |
592 } | 598 } |
593 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != | 599 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != |
594 STDOUT_FILENO) { | 600 STDOUT_FILENO) { |
595 ReportChildError(); | 601 ReportChildError(); |
596 } | 602 } |
597 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != | 603 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != |
598 STDERR_FILENO) { | 604 STDERR_FILENO) { |
599 ReportChildError(); | 605 ReportChildError(); |
600 } | 606 } |
601 } | 607 } |
602 | 608 |
603 void SetupDetachedWithStdio() { | 609 void SetupDetachedWithStdio() { |
604 // Close all open file descriptors except for | 610 // Close all open file descriptors except for |
605 // exec_control_[1], write_out_[0], read_in_[1] and | 611 // exec_control_[1], write_out_[0], read_in_[1] and |
606 // read_err_[1]. | 612 // read_err_[1]. |
607 int max_fds = sysconf(_SC_OPEN_MAX); | 613 int max_fds = sysconf(_SC_OPEN_MAX); |
608 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; | 614 if (max_fds == -1) { |
615 max_fds = _POSIX_OPEN_MAX; | |
616 } | |
609 for (int fd = 0; fd < max_fds; fd++) { | 617 for (int fd = 0; fd < max_fds; fd++) { |
610 if (fd != exec_control_[1] && | 618 if ((fd != exec_control_[1]) && |
611 fd != write_out_[0] && | 619 (fd != write_out_[0]) && |
612 fd != read_in_[1] && | 620 (fd != read_in_[1]) && |
613 fd != read_err_[1]) { | 621 (fd != read_err_[1])) { |
614 VOID_TEMP_FAILURE_RETRY(close(fd)); | 622 VOID_TEMP_FAILURE_RETRY(close(fd)); |
615 } | 623 } |
616 } | 624 } |
617 | 625 |
618 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { | 626 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
619 ReportChildError(); | 627 ReportChildError(); |
620 } | 628 } |
621 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); | 629 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); |
622 | 630 |
623 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { | 631 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 | 732 |
725 const char* path_; | 733 const char* path_; |
726 const char* working_directory_; | 734 const char* working_directory_; |
727 ProcessStartMode mode_; | 735 ProcessStartMode mode_; |
728 intptr_t* in_; | 736 intptr_t* in_; |
729 intptr_t* out_; | 737 intptr_t* out_; |
730 intptr_t* err_; | 738 intptr_t* err_; |
731 intptr_t* id_; | 739 intptr_t* id_; |
732 intptr_t* exit_event_; | 740 intptr_t* exit_event_; |
733 char** os_error_message_; | 741 char** os_error_message_; |
742 | |
743 DISALLOW_ALLOCATION(); | |
744 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); | |
734 }; | 745 }; |
735 | 746 |
736 | 747 |
737 int Process::Start(const char* path, | 748 int Process::Start(const char* path, |
738 char* arguments[], | 749 char* arguments[], |
739 intptr_t arguments_length, | 750 intptr_t arguments_length, |
740 const char* working_directory, | 751 const char* working_directory, |
741 char* environment[], | 752 char* environment[], |
742 intptr_t environment_length, | 753 intptr_t environment_length, |
743 ProcessStartMode mode, | 754 ProcessStartMode mode, |
(...skipping 15 matching lines...) Expand all Loading... | |
759 err, | 770 err, |
760 id, | 771 id, |
761 exit_event, | 772 exit_event, |
762 os_error_message); | 773 os_error_message); |
763 return starter.Start(); | 774 return starter.Start(); |
764 } | 775 } |
765 | 776 |
766 | 777 |
767 class BufferList: public BufferListBase { | 778 class BufferList: public BufferListBase { |
768 public: | 779 public: |
780 BufferList() {} | |
781 | |
769 bool Read(int fd, intptr_t available) { | 782 bool Read(int fd, intptr_t available) { |
770 // Read all available bytes. | 783 // Read all available bytes. |
771 while (available > 0) { | 784 while (available > 0) { |
772 if (free_size_ == 0) Allocate(); | 785 if (free_size_ == 0) { |
786 Allocate(); | |
787 } | |
773 ASSERT(free_size_ > 0); | 788 ASSERT(free_size_ > 0); |
774 ASSERT(free_size_ <= kBufferSize); | 789 ASSERT(free_size_ <= kBufferSize); |
775 intptr_t block_size = dart::Utils::Minimum(free_size_, available); | 790 intptr_t block_size = dart::Utils::Minimum(free_size_, available); |
776 intptr_t bytes = TEMP_FAILURE_RETRY(read( | 791 intptr_t bytes = TEMP_FAILURE_RETRY(read( |
777 fd, | 792 fd, |
778 reinterpret_cast<void*>(FreeSpaceAddress()), | 793 reinterpret_cast<void*>(FreeSpaceAddress()), |
779 block_size)); | 794 block_size)); |
780 if (bytes < 0) return false; | 795 if (bytes < 0) { |
796 return false; | |
797 } | |
781 data_size_ += bytes; | 798 data_size_ += bytes; |
782 free_size_ -= bytes; | 799 free_size_ -= bytes; |
783 available -= bytes; | 800 available -= bytes; |
784 } | 801 } |
785 return true; | 802 return true; |
786 } | 803 } |
804 | |
805 private: | |
806 DISALLOW_COPY_AND_ASSIGN(BufferList); | |
787 }; | 807 }; |
788 | 808 |
789 | 809 |
790 static bool CloseProcessBuffers(struct pollfd fds[3]) { | 810 static bool CloseProcessBuffers(struct pollfd fds[3]) { |
791 int e = errno; | 811 int e = errno; |
792 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); | 812 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); |
793 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); | 813 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); |
794 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); | 814 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); |
795 errno = e; | 815 errno = e; |
796 return false; | 816 return false; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
828 int alive = 3; | 848 int alive = 3; |
829 while (alive > 0) { | 849 while (alive > 0) { |
830 // Blocking call waiting for events from the child process. | 850 // Blocking call waiting for events from the child process. |
831 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { | 851 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { |
832 return CloseProcessBuffers(fds); | 852 return CloseProcessBuffers(fds); |
833 } | 853 } |
834 | 854 |
835 // Process incoming data. | 855 // Process incoming data. |
836 int current_alive = alive; | 856 int current_alive = alive; |
837 for (int i = 0; i < current_alive; i++) { | 857 for (int i = 0; i < current_alive; i++) { |
838 if (fds[i].revents & POLLIN) { | 858 if ((fds[i].revents & POLLIN) != 0) { |
839 intptr_t avail = FDUtils::AvailableBytes(fds[i].fd); | 859 intptr_t avail = FDUtils::AvailableBytes(fds[i].fd); |
840 if (fds[i].fd == out) { | 860 if (fds[i].fd == out) { |
841 if (!out_data.Read(out, avail)) { | 861 if (!out_data.Read(out, avail)) { |
842 return CloseProcessBuffers(fds); | 862 return CloseProcessBuffers(fds); |
843 } | 863 } |
844 } else if (fds[i].fd == err) { | 864 } else if (fds[i].fd == err) { |
845 if (!err_data.Read(err, avail)) { | 865 if (!err_data.Read(err, avail)) { |
846 return CloseProcessBuffers(fds); | 866 return CloseProcessBuffers(fds); |
847 } | 867 } |
848 } else if (fds[i].fd == exit_event) { | 868 } else if (fds[i].fd == exit_event) { |
849 if (avail == 8) { | 869 if (avail == 8) { |
850 intptr_t b = TEMP_FAILURE_RETRY(read(exit_event, | 870 intptr_t b = TEMP_FAILURE_RETRY(read(exit_event, |
851 exit_code_data.bytes, 8)); | 871 exit_code_data.bytes, 8)); |
852 if (b != 8) { | 872 if (b != 8) { |
853 return CloseProcessBuffers(fds); | 873 return CloseProcessBuffers(fds); |
854 } | 874 } |
855 } | 875 } |
856 } else { | 876 } else { |
857 UNREACHABLE(); | 877 UNREACHABLE(); |
858 } | 878 } |
859 } | 879 } |
860 if (fds[i].revents & POLLHUP) { | 880 if ((fds[i].revents & POLLHUP) != 0) { |
861 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); | 881 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); |
862 alive--; | 882 alive--; |
863 if (i < alive) { | 883 if (i < alive) { |
864 fds[i] = fds[alive]; | 884 fds[i] = fds[alive]; |
865 } | 885 } |
866 } | 886 } |
867 } | 887 } |
868 } | 888 } |
869 | 889 |
870 // All handles closed and all data read. | 890 // All handles closed and all data read. |
871 result->set_stdout_data(out_data.GetData()); | 891 result->set_stdout_data(out_data.GetData()); |
872 result->set_stderr_data(err_data.GetData()); | 892 result->set_stderr_data(err_data.GetData()); |
873 | 893 |
874 // Calculate the exit code. | 894 // Calculate the exit code. |
875 intptr_t exit_code = exit_code_data.ints[0]; | 895 intptr_t exit_code = exit_code_data.ints[0]; |
876 intptr_t negative = exit_code_data.ints[1]; | 896 intptr_t negative = exit_code_data.ints[1]; |
877 if (negative) exit_code = -exit_code; | 897 if (negative) { |
898 exit_code = -exit_code; | |
899 } | |
878 result->set_exit_code(exit_code); | 900 result->set_exit_code(exit_code); |
879 | 901 |
880 return true; | 902 return true; |
881 } | 903 } |
882 | 904 |
883 | 905 |
884 bool Process::Kill(intptr_t id, int signal) { | 906 bool Process::Kill(intptr_t id, int signal) { |
885 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); | 907 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); |
886 } | 908 } |
887 | 909 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
929 | 951 |
930 | 952 |
931 intptr_t Process::SetSignalHandler(intptr_t signal) { | 953 intptr_t Process::SetSignalHandler(intptr_t signal) { |
932 bool found = false; | 954 bool found = false; |
933 for (int i = 0; i < kSignalsCount; i++) { | 955 for (int i = 0; i < kSignalsCount; i++) { |
934 if (kSignals[i] == signal) { | 956 if (kSignals[i] == signal) { |
935 found = true; | 957 found = true; |
936 break; | 958 break; |
937 } | 959 } |
938 } | 960 } |
939 if (!found) return -1; | 961 if (!found) { |
962 return -1; | |
963 } | |
940 int fds[2]; | 964 int fds[2]; |
941 if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) { | 965 if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) { |
942 return -1; | 966 return -1; |
943 } | 967 } |
944 if (!FDUtils::SetNonBlocking(fds[0])) { | 968 if (!FDUtils::SetNonBlocking(fds[0])) { |
945 VOID_TEMP_FAILURE_RETRY(close(fds[0])); | 969 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
946 VOID_TEMP_FAILURE_RETRY(close(fds[1])); | 970 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
947 return -1; | 971 return -1; |
948 } | 972 } |
949 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 973 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
(...skipping 29 matching lines...) Expand all Loading... | |
979 | 1003 |
980 void Process::ClearSignalHandler(intptr_t signal) { | 1004 void Process::ClearSignalHandler(intptr_t signal) { |
981 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 1005 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
982 MutexLocker lock(signal_mutex); | 1006 MutexLocker lock(signal_mutex); |
983 SignalInfo* handler = signal_handlers; | 1007 SignalInfo* handler = signal_handlers; |
984 bool unlisten = true; | 1008 bool unlisten = true; |
985 while (handler != NULL) { | 1009 while (handler != NULL) { |
986 bool remove = false; | 1010 bool remove = false; |
987 if (handler->signal() == signal) { | 1011 if (handler->signal() == signal) { |
988 if (handler->port() == Dart_GetMainPortId()) { | 1012 if (handler->port() == Dart_GetMainPortId()) { |
989 if (signal_handlers == handler) signal_handlers = handler->next(); | 1013 if (signal_handlers == handler) { |
1014 signal_handlers = handler->next(); | |
1015 } | |
990 handler->Unlink(); | 1016 handler->Unlink(); |
991 remove = true; | 1017 remove = true; |
992 } else { | 1018 } else { |
993 unlisten = false; | 1019 unlisten = false; |
994 } | 1020 } |
995 } | 1021 } |
996 SignalInfo* next = handler->next(); | 1022 SignalInfo* next = handler->next(); |
997 if (remove) delete handler; | 1023 if (remove) { |
1024 delete handler; | |
1025 } | |
998 handler = next; | 1026 handler = next; |
999 } | 1027 } |
1000 if (unlisten) { | 1028 if (unlisten) { |
1001 struct sigaction act; | 1029 struct sigaction act; |
1002 bzero(&act, sizeof(act)); | 1030 bzero(&act, sizeof(act)); |
1003 act.sa_handler = SIG_DFL; | 1031 act.sa_handler = SIG_DFL; |
1004 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1032 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
1005 } | 1033 } |
1006 } | 1034 } |
1007 | 1035 |
1008 } // namespace bin | 1036 } // namespace bin |
1009 } // namespace dart | 1037 } // namespace dart |
1010 | 1038 |
1011 #endif // defined(TARGET_OS_ANDROID) | 1039 #endif // defined(TARGET_OS_ANDROID) |
OLD | NEW |