Chromium Code Reviews| 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 |