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_MACOS) | 6 #if defined(TARGET_OS_MACOS) |
7 | 7 |
8 #include "bin/process.h" | 8 #include "bin/process.h" |
9 | 9 |
10 #if !TARGET_OS_IOS | 10 #if !TARGET_OS_IOS |
(...skipping 10 matching lines...) Expand all Loading... | |
21 | 21 |
22 #include "bin/dartutils.h" | 22 #include "bin/dartutils.h" |
23 #include "bin/fdutils.h" | 23 #include "bin/fdutils.h" |
24 #include "bin/lockers.h" | 24 #include "bin/lockers.h" |
25 #include "bin/log.h" | 25 #include "bin/log.h" |
26 #include "bin/thread.h" | 26 #include "bin/thread.h" |
27 | 27 |
28 #include "platform/signal_blocker.h" | 28 #include "platform/signal_blocker.h" |
29 #include "platform/utils.h" | 29 #include "platform/utils.h" |
30 | 30 |
31 | |
32 | |
33 namespace dart { | 31 namespace dart { |
34 namespace bin { | 32 namespace bin { |
35 | 33 |
36 // ProcessInfo is used to map a process id to the file descriptor for | 34 // ProcessInfo is used to map a process id to the file descriptor for |
37 // the pipe used to communicate the exit code of the process to Dart. | 35 // the pipe used to communicate the exit code of the process to Dart. |
38 // ProcessInfo objects are kept in the static singly-linked | 36 // ProcessInfo objects are kept in the static singly-linked |
39 // ProcessInfoList. | 37 // ProcessInfoList. |
40 class ProcessInfo { | 38 class ProcessInfo { |
41 public: | 39 public: |
42 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } | 40 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } |
43 ~ProcessInfo() { | 41 ~ProcessInfo() { |
44 int closed = TEMP_FAILURE_RETRY(close(fd_)); | 42 int closed = TEMP_FAILURE_RETRY(close(fd_)); |
45 if (closed != 0) { | 43 if (closed != 0) { |
46 FATAL("Failed to close process exit code pipe"); | 44 FATAL("Failed to close process exit code pipe"); |
47 } | 45 } |
48 } | 46 } |
49 pid_t pid() { return pid_; } | 47 pid_t pid() { return pid_; } |
50 intptr_t fd() { return fd_; } | 48 intptr_t fd() { return fd_; } |
51 ProcessInfo* next() { return next_; } | 49 ProcessInfo* next() { return next_; } |
52 void set_next(ProcessInfo* info) { next_ = info; } | 50 void set_next(ProcessInfo* info) { next_ = info; } |
53 | 51 |
54 private: | 52 private: |
55 pid_t pid_; | 53 pid_t pid_; |
56 intptr_t fd_; | 54 intptr_t fd_; |
57 ProcessInfo* next_; | 55 ProcessInfo* next_; |
56 | |
57 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); | |
58 }; | 58 }; |
59 | 59 |
60 | 60 |
61 // Singly-linked list of ProcessInfo objects for all active processes | 61 // Singly-linked list of ProcessInfo objects for all active processes |
62 // started from Dart. | 62 // started from Dart. |
63 class ProcessInfoList { | 63 class ProcessInfoList { |
64 public: | 64 public: |
65 static void AddProcess(pid_t pid, intptr_t fd) { | 65 static void AddProcess(pid_t pid, intptr_t fd) { |
66 MutexLocker locker(mutex_); | 66 MutexLocker locker(mutex_); |
67 ProcessInfo* info = new ProcessInfo(pid, fd); | 67 ProcessInfo* info = new ProcessInfo(pid, fd); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 } | 102 } |
103 } | 103 } |
104 | 104 |
105 private: | 105 private: |
106 // Linked list of ProcessInfo objects for all active processes | 106 // Linked list of ProcessInfo objects for all active processes |
107 // started from Dart code. | 107 // started from Dart code. |
108 static ProcessInfo* active_processes_; | 108 static ProcessInfo* active_processes_; |
109 // Mutex protecting all accesses to the linked list of active | 109 // Mutex protecting all accesses to the linked list of active |
110 // processes. | 110 // processes. |
111 static Mutex* mutex_; | 111 static Mutex* mutex_; |
112 | |
113 DISALLOW_ALLOCATION(); | |
114 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); | |
112 }; | 115 }; |
113 | 116 |
114 | 117 |
115 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 118 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
116 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 119 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
117 | 120 |
118 | 121 |
119 // The exit code handler sets up a separate thread which waits for child | 122 // The exit code handler sets up a separate thread which waits for child |
120 // processes to terminate. That separate thread can then get the exit code from | 123 // processes to terminate. That separate thread can then get the exit code from |
121 // processes that have exited and communicate it to Dart through the | 124 // processes that have exited and communicate it to Dart through the |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 } | 201 } |
199 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); | 202 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); |
200 if (exit_code_fd != 0) { | 203 if (exit_code_fd != 0) { |
201 int message[2] = { exit_code, negative }; | 204 int message[2] = { exit_code, negative }; |
202 ssize_t result = | 205 ssize_t result = |
203 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); | 206 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); |
204 // If the process has been closed, the read end of the exit | 207 // If the process has been closed, the read end of the exit |
205 // pipe has been closed. It is therefore not a problem that | 208 // pipe has been closed. It is therefore not a problem that |
206 // write fails with a broken pipe error. Other errors should | 209 // write fails with a broken pipe error. Other errors should |
207 // not happen. | 210 // not happen. |
208 if (result != -1 && result != sizeof(message)) { | 211 if ((result != -1) && (result != sizeof(message))) { |
209 FATAL("Failed to write entire process exit message"); | 212 FATAL("Failed to write entire process exit message"); |
210 } else if (result == -1 && errno != EPIPE) { | 213 } else if ((result == -1) && (errno != EPIPE)) { |
211 FATAL1("Failed to write exit code: %d", errno); | 214 FATAL1("Failed to write exit code: %d", errno); |
212 } | 215 } |
213 ProcessInfoList::RemoveProcess(pid); | 216 ProcessInfoList::RemoveProcess(pid); |
214 { | 217 { |
215 MonitorLocker locker(monitor_); | 218 MonitorLocker locker(monitor_); |
216 process_count_--; | 219 process_count_--; |
217 } | 220 } |
218 } | 221 } |
219 } | 222 } |
220 } | 223 } |
221 } | 224 } |
222 | 225 |
223 static bool terminate_done_; | 226 static bool terminate_done_; |
224 static int process_count_; | 227 static int process_count_; |
225 static bool running_; | 228 static bool running_; |
226 static Monitor* monitor_; | 229 static Monitor* monitor_; |
230 | |
231 DISALLOW_ALLOCATION(); | |
232 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); | |
227 }; | 233 }; |
228 | 234 |
229 | 235 |
230 bool ExitCodeHandler::running_ = false; | 236 bool ExitCodeHandler::running_ = false; |
231 int ExitCodeHandler::process_count_ = 0; | 237 int ExitCodeHandler::process_count_ = 0; |
232 bool ExitCodeHandler::terminate_done_ = false; | 238 bool ExitCodeHandler::terminate_done_ = false; |
233 Monitor* ExitCodeHandler::monitor_ = new Monitor(); | 239 Monitor* ExitCodeHandler::monitor_ = new Monitor(); |
234 | 240 |
235 | 241 |
236 class ProcessStarter { | 242 class ProcessStarter { |
(...skipping 22 matching lines...) Expand all Loading... | |
259 os_error_message_(os_error_message) { | 265 os_error_message_(os_error_message) { |
260 read_in_[0] = -1; | 266 read_in_[0] = -1; |
261 read_in_[1] = -1; | 267 read_in_[1] = -1; |
262 read_err_[0] = -1; | 268 read_err_[0] = -1; |
263 read_err_[1] = -1; | 269 read_err_[1] = -1; |
264 write_out_[0] = -1; | 270 write_out_[0] = -1; |
265 write_out_[1] = -1; | 271 write_out_[1] = -1; |
266 exec_control_[0] = -1; | 272 exec_control_[0] = -1; |
267 exec_control_[1] = -1; | 273 exec_control_[1] = -1; |
268 | 274 |
269 program_arguments_ = new char*[arguments_length + 2]; | 275 program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate( |
zra
2016/03/15 18:12:29
Changed to scope allocation.
| |
276 (arguments_length + 2) * sizeof(*program_arguments_))); | |
270 program_arguments_[0] = const_cast<char*>(path_); | 277 program_arguments_[0] = const_cast<char*>(path_); |
271 for (int i = 0; i < arguments_length; i++) { | 278 for (int i = 0; i < arguments_length; i++) { |
272 program_arguments_[i + 1] = arguments[i]; | 279 program_arguments_[i + 1] = arguments[i]; |
273 } | 280 } |
274 program_arguments_[arguments_length + 1] = NULL; | 281 program_arguments_[arguments_length + 1] = NULL; |
275 | 282 |
276 program_environment_ = NULL; | 283 program_environment_ = NULL; |
277 if (environment != NULL) { | 284 if (environment != NULL) { |
278 program_environment_ = new char*[environment_length + 1]; | 285 program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate( |
zra
2016/03/15 18:12:29
ditto.
| |
286 (environment_length + 1) * sizeof(*program_environment_))); | |
279 for (int i = 0; i < environment_length; i++) { | 287 for (int i = 0; i < environment_length; i++) { |
280 program_environment_[i] = environment[i]; | 288 program_environment_[i] = environment[i]; |
281 } | 289 } |
282 program_environment_[environment_length] = NULL; | 290 program_environment_[environment_length] = NULL; |
283 } | 291 } |
284 } | 292 } |
285 | 293 |
286 | 294 |
287 ~ProcessStarter() { | |
288 delete[] program_arguments_; | |
289 delete[] program_environment_; | |
290 } | |
291 | |
292 | |
293 int Start() { | 295 int Start() { |
294 // Create pipes required. | 296 // Create pipes required. |
295 int err = CreatePipes(); | 297 int err = CreatePipes(); |
296 if (err != 0) { | 298 if (err != 0) { |
297 return err; | 299 return err; |
298 } | 300 } |
299 | 301 |
300 // Fork to create the new process. | 302 // Fork to create the new process. |
301 pid_t pid = TEMP_FAILURE_RETRY(fork()); | 303 pid_t pid = TEMP_FAILURE_RETRY(fork()); |
302 if (pid < 0) { | 304 if (pid < 0) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 pid = TEMP_FAILURE_RETRY(fork()); | 504 pid = TEMP_FAILURE_RETRY(fork()); |
503 if (pid < 0) { | 505 if (pid < 0) { |
504 ReportChildError(); | 506 ReportChildError(); |
505 } else if (pid == 0) { | 507 } else if (pid == 0) { |
506 if (mode_ == kDetached) { | 508 if (mode_ == kDetached) { |
507 SetupDetached(); | 509 SetupDetached(); |
508 } else { | 510 } else { |
509 SetupDetachedWithStdio(); | 511 SetupDetachedWithStdio(); |
510 } | 512 } |
511 | 513 |
512 if (working_directory_ != NULL && | 514 if ((working_directory_ != NULL) && |
513 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 515 (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) { |
514 ReportChildError(); | 516 ReportChildError(); |
515 } | 517 } |
516 | 518 |
517 // Report the final PID and do the exec. | 519 // Report the final PID and do the exec. |
518 ReportPid(getpid()); // getpid cannot fail. | 520 ReportPid(getpid()); // getpid cannot fail. |
519 VOID_TEMP_FAILURE_RETRY( | 521 VOID_TEMP_FAILURE_RETRY( |
520 execvp(path_, const_cast<char* const*>(program_arguments_))); | 522 execvp(path_, const_cast<char* const*>(program_arguments_))); |
521 ReportChildError(); | 523 ReportChildError(); |
522 } else { | 524 } else { |
523 // Exit the intermeiate process. | 525 // Exit the intermeiate process. |
(...skipping 23 matching lines...) Expand all Loading... | |
547 return 0; | 549 return 0; |
548 } | 550 } |
549 | 551 |
550 | 552 |
551 int ReadExecResult() { | 553 int ReadExecResult() { |
552 int child_errno; | 554 int child_errno; |
553 int bytes_read = -1; | 555 int bytes_read = -1; |
554 // Read exec result from child. If no data is returned the exec was | 556 // Read exec result from child. If no data is returned the exec was |
555 // successful and the exec call closed the pipe. Otherwise the errno | 557 // successful and the exec call closed the pipe. Otherwise the errno |
556 // is written to the pipe. | 558 // is written to the pipe. |
557 bytes_read = | 559 bytes_read = FDUtils::ReadFromBlocking( |
558 FDUtils::ReadFromBlocking( | 560 exec_control_[0], &child_errno, sizeof(child_errno)); |
559 exec_control_[0], &child_errno, sizeof(child_errno)); | |
560 if (bytes_read == sizeof(child_errno)) { | 561 if (bytes_read == sizeof(child_errno)) { |
561 ReadChildError(); | 562 ReadChildError(); |
562 return child_errno; | 563 return child_errno; |
563 } else if (bytes_read == -1) { | 564 } else if (bytes_read == -1) { |
564 return errno; | 565 return errno; |
565 } | 566 } |
566 return 0; | 567 return 0; |
567 } | 568 } |
568 | 569 |
569 | 570 |
570 int ReadDetachedExecResult(pid_t *pid) { | 571 int ReadDetachedExecResult(pid_t *pid) { |
571 int child_errno; | 572 int child_errno; |
572 int bytes_read = -1; | 573 int bytes_read = -1; |
573 // Read exec result from child. If only pid data is returned the exec was | 574 // Read exec result from child. If only pid data is returned the exec was |
574 // successful and the exec call closed the pipe. Otherwise the errno | 575 // successful and the exec call closed the pipe. Otherwise the errno |
575 // is written to the pipe as well. | 576 // is written to the pipe as well. |
576 int result[2]; | 577 int result[2]; |
577 bytes_read = | 578 bytes_read = |
578 FDUtils::ReadFromBlocking( | 579 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result)); |
579 exec_control_[0], result, sizeof(result)); | |
580 if (bytes_read == sizeof(int)) { | 580 if (bytes_read == sizeof(int)) { |
581 *pid = result[0]; | 581 *pid = result[0]; |
582 } else if (bytes_read == 2 * sizeof(int)) { | 582 } else if (bytes_read == 2 * sizeof(int)) { |
583 *pid = result[0]; | 583 *pid = result[0]; |
584 child_errno = result[1]; | 584 child_errno = result[1]; |
585 ReadChildError(); | 585 ReadChildError(); |
586 return child_errno; | 586 return child_errno; |
587 } else if (bytes_read == -1) { | 587 } else if (bytes_read == -1) { |
588 return errno; | 588 return errno; |
589 } | 589 } |
590 return 0; | 590 return 0; |
591 } | 591 } |
592 | 592 |
593 | 593 |
594 void SetupDetached() { | 594 void SetupDetached() { |
595 ASSERT(mode_ == kDetached); | 595 ASSERT(mode_ == kDetached); |
596 | 596 |
597 // Close all open file descriptors except for exec_control_[1]. | 597 // Close all open file descriptors except for exec_control_[1]. |
598 int max_fds = sysconf(_SC_OPEN_MAX); | 598 int max_fds = sysconf(_SC_OPEN_MAX); |
599 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; | 599 if (max_fds == -1) { |
600 max_fds = _POSIX_OPEN_MAX; | |
601 } | |
600 for (int fd = 0; fd < max_fds; fd++) { | 602 for (int fd = 0; fd < max_fds; fd++) { |
601 if (fd != exec_control_[1]) { | 603 if (fd != exec_control_[1]) { |
602 VOID_TEMP_FAILURE_RETRY(close(fd)); | 604 VOID_TEMP_FAILURE_RETRY(close(fd)); |
603 } | 605 } |
604 } | 606 } |
605 | 607 |
606 // Re-open stdin, stdout and stderr and connect them to /dev/null. | 608 // Re-open stdin, stdout and stderr and connect them to /dev/null. |
607 // The loop above should already have closed all of them, so | 609 // The loop above should already have closed all of them, so |
608 // creating new file descriptors should start at STDIN_FILENO. | 610 // creating new file descriptors should start at STDIN_FILENO. |
609 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); | 611 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); |
610 if (fd != STDIN_FILENO) { | 612 if (fd != STDIN_FILENO) { |
611 ReportChildError(); | 613 ReportChildError(); |
612 } | 614 } |
613 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != | 615 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != |
614 STDOUT_FILENO) { | 616 STDOUT_FILENO) { |
615 ReportChildError(); | 617 ReportChildError(); |
616 } | 618 } |
617 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != | 619 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != |
618 STDERR_FILENO) { | 620 STDERR_FILENO) { |
619 ReportChildError(); | 621 ReportChildError(); |
620 } | 622 } |
621 } | 623 } |
622 | 624 |
623 void SetupDetachedWithStdio() { | 625 void SetupDetachedWithStdio() { |
624 // Close all open file descriptors except for | 626 // Close all open file descriptors except for |
625 // exec_control_[1], write_out_[0], read_in_[1] and | 627 // exec_control_[1], write_out_[0], read_in_[1] and |
626 // read_err_[1]. | 628 // read_err_[1]. |
627 int max_fds = sysconf(_SC_OPEN_MAX); | 629 int max_fds = sysconf(_SC_OPEN_MAX); |
628 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; | 630 if (max_fds == -1) { |
631 max_fds = _POSIX_OPEN_MAX; | |
632 } | |
629 for (int fd = 0; fd < max_fds; fd++) { | 633 for (int fd = 0; fd < max_fds; fd++) { |
630 if (fd != exec_control_[1] && | 634 if ((fd != exec_control_[1]) && |
631 fd != write_out_[0] && | 635 (fd != write_out_[0]) && |
632 fd != read_in_[1] && | 636 (fd != read_in_[1]) && |
633 fd != read_err_[1]) { | 637 (fd != read_err_[1])) { |
634 VOID_TEMP_FAILURE_RETRY(close(fd)); | 638 VOID_TEMP_FAILURE_RETRY(close(fd)); |
635 } | 639 } |
636 } | 640 } |
637 | 641 |
638 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { | 642 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
639 ReportChildError(); | 643 ReportChildError(); |
640 } | 644 } |
641 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); | 645 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); |
642 | 646 |
643 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { | 647 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
(...skipping 29 matching lines...) Expand all Loading... | |
673 } | 677 } |
674 | 678 |
675 | 679 |
676 void ReportChildError() { | 680 void ReportChildError() { |
677 // In the case of failure in the child process write the errno and | 681 // In the case of failure in the child process write the errno and |
678 // the OS error message to the exec control pipe and exit. | 682 // the OS error message to the exec control pipe and exit. |
679 int child_errno = errno; | 683 int child_errno = errno; |
680 const int kBufferSize = 1024; | 684 const int kBufferSize = 1024; |
681 char os_error_message[kBufferSize]; | 685 char os_error_message[kBufferSize]; |
682 Utils::StrError(errno, os_error_message, kBufferSize); | 686 Utils::StrError(errno, os_error_message, kBufferSize); |
683 int bytes_written = | 687 int bytes_written = FDUtils::WriteToBlocking( |
684 FDUtils::WriteToBlocking( | 688 exec_control_[1], &child_errno, sizeof(child_errno)); |
685 exec_control_[1], &child_errno, sizeof(child_errno)); | |
686 if (bytes_written == sizeof(child_errno)) { | 689 if (bytes_written == sizeof(child_errno)) { |
687 FDUtils::WriteToBlocking( | 690 FDUtils::WriteToBlocking( |
688 exec_control_[1], os_error_message, strlen(os_error_message) + 1); | 691 exec_control_[1], os_error_message, strlen(os_error_message) + 1); |
689 } | 692 } |
690 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); | 693 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); |
691 exit(1); | 694 exit(1); |
692 } | 695 } |
693 | 696 |
694 | 697 |
695 void ReportPid(int pid) { | 698 void ReportPid(int pid) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 | 747 |
745 const char* path_; | 748 const char* path_; |
746 const char* working_directory_; | 749 const char* working_directory_; |
747 ProcessStartMode mode_; | 750 ProcessStartMode mode_; |
748 intptr_t* in_; | 751 intptr_t* in_; |
749 intptr_t* out_; | 752 intptr_t* out_; |
750 intptr_t* err_; | 753 intptr_t* err_; |
751 intptr_t* id_; | 754 intptr_t* id_; |
752 intptr_t* exit_event_; | 755 intptr_t* exit_event_; |
753 char** os_error_message_; | 756 char** os_error_message_; |
757 | |
758 DISALLOW_ALLOCATION(); | |
759 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); | |
754 }; | 760 }; |
755 | 761 |
756 | 762 |
757 int Process::Start(const char* path, | 763 int Process::Start(const char* path, |
758 char* arguments[], | 764 char* arguments[], |
759 intptr_t arguments_length, | 765 intptr_t arguments_length, |
760 const char* working_directory, | 766 const char* working_directory, |
761 char* environment[], | 767 char* environment[], |
762 intptr_t environment_length, | 768 intptr_t environment_length, |
763 ProcessStartMode mode, | 769 ProcessStartMode mode, |
(...skipping 15 matching lines...) Expand all Loading... | |
779 err, | 785 err, |
780 id, | 786 id, |
781 exit_event, | 787 exit_event, |
782 os_error_message); | 788 os_error_message); |
783 return starter.Start(); | 789 return starter.Start(); |
784 } | 790 } |
785 | 791 |
786 | 792 |
787 class BufferList: public BufferListBase { | 793 class BufferList: public BufferListBase { |
788 public: | 794 public: |
795 BufferList() {} | |
796 | |
789 bool Read(int fd, intptr_t available) { | 797 bool Read(int fd, intptr_t available) { |
790 // Read all available bytes. | 798 // Read all available bytes. |
791 while (available > 0) { | 799 while (available > 0) { |
792 if (free_size_ == 0) Allocate(); | 800 if (free_size_ == 0) { |
801 Allocate(); | |
802 } | |
793 ASSERT(free_size_ > 0); | 803 ASSERT(free_size_ > 0); |
794 ASSERT(free_size_ <= kBufferSize); | 804 ASSERT(free_size_ <= kBufferSize); |
795 size_t block_size = dart::Utils::Minimum(free_size_, available); | 805 size_t block_size = dart::Utils::Minimum(free_size_, available); |
796 ssize_t bytes = TEMP_FAILURE_RETRY(read( | 806 ssize_t bytes = TEMP_FAILURE_RETRY(read( |
797 fd, | 807 fd, |
798 reinterpret_cast<void*>(FreeSpaceAddress()), | 808 reinterpret_cast<void*>(FreeSpaceAddress()), |
799 block_size)); | 809 block_size)); |
800 if (bytes < 0) return false; | 810 if (bytes < 0) { |
811 return false; | |
812 } | |
801 data_size_ += bytes; | 813 data_size_ += bytes; |
802 free_size_ -= bytes; | 814 free_size_ -= bytes; |
803 available -= bytes; | 815 available -= bytes; |
804 } | 816 } |
805 return true; | 817 return true; |
806 } | 818 } |
819 | |
820 private: | |
821 DISALLOW_COPY_AND_ASSIGN(BufferList); | |
807 }; | 822 }; |
808 | 823 |
809 | 824 |
810 static bool CloseProcessBuffers(struct pollfd fds[3]) { | 825 static bool CloseProcessBuffers(struct pollfd fds[3]) { |
811 int e = errno; | 826 int e = errno; |
812 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); | 827 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); |
813 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); | 828 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); |
814 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); | 829 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); |
815 errno = e; | 830 errno = e; |
816 return false; | 831 return false; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 while (alive > 0) { | 864 while (alive > 0) { |
850 // Blocking call waiting for events from the child process. | 865 // Blocking call waiting for events from the child process. |
851 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { | 866 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { |
852 return CloseProcessBuffers(fds); | 867 return CloseProcessBuffers(fds); |
853 } | 868 } |
854 | 869 |
855 // Process incoming data. | 870 // Process incoming data. |
856 int current_alive = alive; | 871 int current_alive = alive; |
857 for (int i = 0; i < current_alive; i++) { | 872 for (int i = 0; i < current_alive; i++) { |
858 intptr_t avail; | 873 intptr_t avail; |
859 if (fds[i].revents & POLLIN) { | 874 if ((fds[i].revents & POLLIN) != 0) { |
860 avail = FDUtils::AvailableBytes(fds[i].fd); | 875 avail = FDUtils::AvailableBytes(fds[i].fd); |
861 // On Mac OS POLLIN can be set with zero available | 876 // On Mac OS POLLIN can be set with zero available |
862 // bytes. POLLHUP is most likely also set in this case. | 877 // bytes. POLLHUP is most likely also set in this case. |
863 if (avail > 0) { | 878 if (avail > 0) { |
864 if (fds[i].fd == out) { | 879 if (fds[i].fd == out) { |
865 if (!out_data.Read(out, avail)) { | 880 if (!out_data.Read(out, avail)) { |
866 return CloseProcessBuffers(fds); | 881 return CloseProcessBuffers(fds); |
867 } | 882 } |
868 } else if (fds[i].fd == err) { | 883 } else if (fds[i].fd == err) { |
869 if (!err_data.Read(err, avail)) { | 884 if (!err_data.Read(err, avail)) { |
870 return CloseProcessBuffers(fds); | 885 return CloseProcessBuffers(fds); |
871 } | 886 } |
872 } else if (fds[i].fd == exit_event) { | 887 } else if (fds[i].fd == exit_event) { |
873 if (avail == 8) { | 888 if (avail == 8) { |
874 intptr_t b = TEMP_FAILURE_RETRY(read(fds[i].fd, | 889 intptr_t b = TEMP_FAILURE_RETRY(read(fds[i].fd, |
875 exit_code_data.bytes, 8)); | 890 exit_code_data.bytes, 8)); |
876 if (b != 8) { | 891 if (b != 8) { |
877 return CloseProcessBuffers(fds); | 892 return CloseProcessBuffers(fds); |
878 } | 893 } |
879 } | 894 } |
880 } else { | 895 } else { |
881 UNREACHABLE(); | 896 UNREACHABLE(); |
882 } | 897 } |
883 } | 898 } |
884 } | 899 } |
885 if (fds[i].revents & POLLHUP || | 900 if (((fds[i].revents & POLLHUP) != 0) || |
886 ((fds[i].revents & POLLIN) && avail == 0)) { | 901 (((fds[i].revents & POLLIN) != 0) && (avail == 0))) { |
887 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); | 902 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); |
888 alive--; | 903 alive--; |
889 if (i < alive) { | 904 if (i < alive) { |
890 fds[i] = fds[alive]; | 905 fds[i] = fds[alive]; |
891 } | 906 } |
892 } | 907 } |
893 } | 908 } |
894 } | 909 } |
895 | 910 |
896 // All handles closed and all data read. | 911 // All handles closed and all data read. |
897 result->set_stdout_data(out_data.GetData()); | 912 result->set_stdout_data(out_data.GetData()); |
898 result->set_stderr_data(err_data.GetData()); | 913 result->set_stderr_data(err_data.GetData()); |
899 | 914 |
900 // Calculate the exit code. | 915 // Calculate the exit code. |
901 intptr_t exit_code = exit_code_data.ints[0]; | 916 intptr_t exit_code = exit_code_data.ints[0]; |
902 intptr_t negative = exit_code_data.ints[1]; | 917 intptr_t negative = exit_code_data.ints[1]; |
903 if (negative) exit_code = -exit_code; | 918 if (negative) { |
919 exit_code = -exit_code; | |
920 } | |
904 result->set_exit_code(exit_code); | 921 result->set_exit_code(exit_code); |
905 | 922 |
906 return true; | 923 return true; |
907 } | 924 } |
908 | 925 |
909 | 926 |
910 static int SignalMap(intptr_t id) { | 927 static int SignalMap(intptr_t id) { |
911 switch (static_cast<ProcessSignals>(id)) { | 928 switch (static_cast<ProcessSignals>(id)) { |
912 case kSighup: return SIGHUP; | 929 case kSighup: return SIGHUP; |
913 case kSigint: return SIGINT; | 930 case kSigint: return SIGINT; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
985 int value = 0; | 1002 int value = 0; |
986 VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1)); | 1003 VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1)); |
987 } | 1004 } |
988 handler = handler->next(); | 1005 handler = handler->next(); |
989 } | 1006 } |
990 } | 1007 } |
991 | 1008 |
992 | 1009 |
993 intptr_t Process::SetSignalHandler(intptr_t signal) { | 1010 intptr_t Process::SetSignalHandler(intptr_t signal) { |
994 signal = SignalMap(signal); | 1011 signal = SignalMap(signal); |
995 if (signal == -1) return -1; | 1012 if (signal == -1) { |
1013 return -1; | |
1014 } | |
996 bool found = false; | 1015 bool found = false; |
997 for (int i = 0; i < kSignalsCount; i++) { | 1016 for (int i = 0; i < kSignalsCount; i++) { |
998 if (kSignals[i] == signal) { | 1017 if (kSignals[i] == signal) { |
999 found = true; | 1018 found = true; |
1000 break; | 1019 break; |
1001 } | 1020 } |
1002 } | 1021 } |
1003 if (!found) return -1; | 1022 if (!found) { |
1023 return -1; | |
1024 } | |
1004 int fds[2]; | 1025 int fds[2]; |
1005 if (NO_RETRY_EXPECTED(pipe(fds)) != 0) { | 1026 if (NO_RETRY_EXPECTED(pipe(fds)) != 0) { |
1006 return -1; | 1027 return -1; |
1007 } | 1028 } |
1008 if (!FDUtils::SetCloseOnExec(fds[0]) || | 1029 if (!FDUtils::SetCloseOnExec(fds[0]) || |
1009 !FDUtils::SetCloseOnExec(fds[1]) || | 1030 !FDUtils::SetCloseOnExec(fds[1]) || |
1010 !FDUtils::SetNonBlocking(fds[0])) { | 1031 !FDUtils::SetNonBlocking(fds[0])) { |
1011 VOID_TEMP_FAILURE_RETRY(close(fds[0])); | 1032 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
1012 VOID_TEMP_FAILURE_RETRY(close(fds[1])); | 1033 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
1013 return -1; | 1034 return -1; |
(...skipping 24 matching lines...) Expand all Loading... | |
1038 return -1; | 1059 return -1; |
1039 } | 1060 } |
1040 } | 1061 } |
1041 signal_handlers = new SignalInfo(fds[1], signal, signal_handlers); | 1062 signal_handlers = new SignalInfo(fds[1], signal, signal_handlers); |
1042 return fds[0]; | 1063 return fds[0]; |
1043 } | 1064 } |
1044 | 1065 |
1045 | 1066 |
1046 void Process::ClearSignalHandler(intptr_t signal) { | 1067 void Process::ClearSignalHandler(intptr_t signal) { |
1047 signal = SignalMap(signal); | 1068 signal = SignalMap(signal); |
1048 if (signal == -1) return; | 1069 if (signal == -1) { |
1070 return; | |
1071 } | |
1049 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 1072 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
1050 MutexLocker lock(signal_mutex); | 1073 MutexLocker lock(signal_mutex); |
1051 SignalInfo* handler = signal_handlers; | 1074 SignalInfo* handler = signal_handlers; |
1052 bool unlisten = true; | 1075 bool unlisten = true; |
1053 while (handler != NULL) { | 1076 while (handler != NULL) { |
1054 bool remove = false; | 1077 bool remove = false; |
1055 if (handler->signal() == signal) { | 1078 if (handler->signal() == signal) { |
1056 if (handler->port() == Dart_GetMainPortId()) { | 1079 if (handler->port() == Dart_GetMainPortId()) { |
1057 if (signal_handlers == handler) signal_handlers = handler->next(); | 1080 if (signal_handlers == handler) { |
1081 signal_handlers = handler->next(); | |
1082 } | |
1058 handler->Unlink(); | 1083 handler->Unlink(); |
1059 remove = true; | 1084 remove = true; |
1060 } else { | 1085 } else { |
1061 unlisten = false; | 1086 unlisten = false; |
1062 } | 1087 } |
1063 } | 1088 } |
1064 SignalInfo* next = handler->next(); | 1089 SignalInfo* next = handler->next(); |
1065 if (remove) delete handler; | 1090 if (remove) { |
1091 delete handler; | |
1092 } | |
1066 handler = next; | 1093 handler = next; |
1067 } | 1094 } |
1068 if (unlisten) { | 1095 if (unlisten) { |
1069 struct sigaction act; | 1096 struct sigaction act; |
1070 bzero(&act, sizeof(act)); | 1097 bzero(&act, sizeof(act)); |
1071 act.sa_handler = SIG_DFL; | 1098 act.sa_handler = SIG_DFL; |
1072 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1099 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
1073 } | 1100 } |
1074 } | 1101 } |
1075 | 1102 |
1076 } // namespace bin | 1103 } // namespace bin |
1077 } // namespace dart | 1104 } // namespace dart |
1078 | 1105 |
1079 #endif // defined(TARGET_OS_MACOS) | 1106 #endif // defined(TARGET_OS_MACOS) |
OLD | NEW |