| 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 !defined(TARGET_OS_IOS) | 10 #if !defined(TARGET_OS_IOS) |
| 11 #include <crt_externs.h> // NOLINT | 11 #include <crt_externs.h> // NOLINT |
| 12 #endif | 12 #endif |
| 13 #include <errno.h> // NOLINT | 13 #include <errno.h> // NOLINT |
| 14 #include <fcntl.h> // NOLINT | 14 #include <fcntl.h> // NOLINT |
| 15 #include <poll.h> // NOLINT | 15 #include <poll.h> // NOLINT |
| 16 #include <signal.h> // NOLINT | 16 #include <signal.h> // NOLINT |
| 17 #include <stdio.h> // NOLINT | 17 #include <stdio.h> // NOLINT |
| 18 #include <stdlib.h> // NOLINT | 18 #include <stdlib.h> // NOLINT |
| 19 #include <string.h> // NOLINT | 19 #include <string.h> // NOLINT |
| 20 #include <unistd.h> // NOLINT | 20 #include <unistd.h> // NOLINT |
| 21 | 21 |
| 22 #include "bin/fdutils.h" | 22 #include "bin/fdutils.h" |
| 23 #include "bin/lockers.h" | 23 #include "bin/lockers.h" |
| 24 #include "bin/log.h" | 24 #include "bin/log.h" |
| 25 #include "bin/thread.h" | 25 #include "bin/thread.h" |
| 26 | 26 |
| 27 #include "platform/signal_blocker.h" | 27 #include "platform/signal_blocker.h" |
| 28 | 28 |
| 29 | 29 |
| 30 extern char** environ; | |
| 31 | |
| 32 | 30 |
| 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: |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 if (!running_) { | 148 if (!running_) { |
| 151 return; | 149 return; |
| 152 } | 150 } |
| 153 | 151 |
| 154 // Set terminate_done_ to false, so we can use it as a guard for our | 152 // Set terminate_done_ to false, so we can use it as a guard for our |
| 155 // monitor. | 153 // monitor. |
| 156 running_ = false; | 154 running_ = false; |
| 157 | 155 |
| 158 // Fork to wake up waitpid. | 156 // Fork to wake up waitpid. |
| 159 if (TEMP_FAILURE_RETRY(fork()) == 0) { | 157 if (TEMP_FAILURE_RETRY(fork()) == 0) { |
| 160 _exit(0); | 158 exit(0); |
| 161 } | 159 } |
| 162 | 160 |
| 163 monitor_->Notify(); | 161 monitor_->Notify(); |
| 164 | 162 |
| 165 while (!terminate_done_) { | 163 while (!terminate_done_) { |
| 166 monitor_->Wait(Monitor::kNoTimeout); | 164 monitor_->Wait(Monitor::kNoTimeout); |
| 167 } | 165 } |
| 168 } | 166 } |
| 169 | 167 |
| 170 private: | 168 private: |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 return 0; | 416 return 0; |
| 419 } | 417 } |
| 420 | 418 |
| 421 | 419 |
| 422 void NewProcess() { | 420 void NewProcess() { |
| 423 // Wait for parent process before setting up the child process. | 421 // Wait for parent process before setting up the child process. |
| 424 char msg; | 422 char msg; |
| 425 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); | 423 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); |
| 426 if (bytes_read != sizeof(msg)) { | 424 if (bytes_read != sizeof(msg)) { |
| 427 perror("Failed receiving notification message"); | 425 perror("Failed receiving notification message"); |
| 428 _exit(1); | 426 exit(1); |
| 429 } | 427 } |
| 430 if (mode_ == kNormal) { | 428 if (mode_ == kNormal) { |
| 431 ExecProcess(); | 429 ExecProcess(); |
| 432 } else { | 430 } else { |
| 433 ExecDetachedProcess(); | 431 ExecDetachedProcess(); |
| 434 } | 432 } |
| 435 } | 433 } |
| 436 | 434 |
| 437 | 435 |
| 438 void ExecProcess() { | 436 void ExecProcess() { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 507 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { |
| 510 ReportChildError(); | 508 ReportChildError(); |
| 511 } | 509 } |
| 512 | 510 |
| 513 // Report the final PID and do the exec. | 511 // Report the final PID and do the exec. |
| 514 ReportPid(getpid()); // getpid cannot fail. | 512 ReportPid(getpid()); // getpid cannot fail. |
| 515 VOID_TEMP_FAILURE_RETRY( | 513 VOID_TEMP_FAILURE_RETRY( |
| 516 execvp(path_, const_cast<char* const*>(program_arguments_))); | 514 execvp(path_, const_cast<char* const*>(program_arguments_))); |
| 517 ReportChildError(); | 515 ReportChildError(); |
| 518 } else { | 516 } else { |
| 519 // Exit the intermediate process. | 517 // Exit the intermeiate process. |
| 520 _exit(0); | 518 exit(0); |
| 521 } | 519 } |
| 522 } | 520 } |
| 523 } else { | 521 } else { |
| 524 // Exit the intermediate process. | 522 // Exit the intermeiate process. |
| 525 _exit(0); | 523 exit(0); |
| 526 } | 524 } |
| 527 } | 525 } |
| 528 | 526 |
| 529 | 527 |
| 530 int RegisterProcess(pid_t pid) { | 528 int RegisterProcess(pid_t pid) { |
| 531 int result; | 529 int result; |
| 532 int event_fds[2]; | 530 int event_fds[2]; |
| 533 result = TEMP_FAILURE_RETRY(pipe(event_fds)); | 531 result = TEMP_FAILURE_RETRY(pipe(event_fds)); |
| 534 if (result < 0) { | 532 if (result < 0) { |
| 535 return CleanupAndReturnError(); | 533 return CleanupAndReturnError(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 547 int ReadExecResult() { | 545 int ReadExecResult() { |
| 548 int child_errno; | 546 int child_errno; |
| 549 int bytes_read = -1; | 547 int bytes_read = -1; |
| 550 // Read exec result from child. If no data is returned the exec was | 548 // Read exec result from child. If no data is returned the exec was |
| 551 // successful and the exec call closed the pipe. Otherwise the errno | 549 // successful and the exec call closed the pipe. Otherwise the errno |
| 552 // is written to the pipe. | 550 // is written to the pipe. |
| 553 bytes_read = | 551 bytes_read = |
| 554 FDUtils::ReadFromBlocking( | 552 FDUtils::ReadFromBlocking( |
| 555 exec_control_[0], &child_errno, sizeof(child_errno)); | 553 exec_control_[0], &child_errno, sizeof(child_errno)); |
| 556 if (bytes_read == sizeof(child_errno)) { | 554 if (bytes_read == sizeof(child_errno)) { |
| 557 SetOSErrorMessage(child_errno); | 555 ReadChildError(); |
| 558 return child_errno; | 556 return child_errno; |
| 559 } else if (bytes_read == -1) { | 557 } else if (bytes_read == -1) { |
| 560 return errno; | 558 return errno; |
| 561 } | 559 } |
| 562 return 0; | 560 return 0; |
| 563 } | 561 } |
| 564 | 562 |
| 565 | 563 |
| 566 int ReadDetachedExecResult(pid_t *pid) { | 564 int ReadDetachedExecResult(pid_t *pid) { |
| 567 int child_errno; | 565 int child_errno; |
| 568 int bytes_read = -1; | 566 int bytes_read = -1; |
| 569 // Read exec result from child. If only pid data is returned the exec was | 567 // Read exec result from child. If only pid data is returned the exec was |
| 570 // successful and the exec call closed the pipe. Otherwise the errno | 568 // successful and the exec call closed the pipe. Otherwise the errno |
| 571 // is written to the pipe as well. | 569 // is written to the pipe as well. |
| 572 int result[2]; | 570 int result[2]; |
| 573 bytes_read = | 571 bytes_read = |
| 574 FDUtils::ReadFromBlocking( | 572 FDUtils::ReadFromBlocking( |
| 575 exec_control_[0], result, sizeof(result)); | 573 exec_control_[0], result, sizeof(result)); |
| 576 if (bytes_read == sizeof(int)) { | 574 if (bytes_read == sizeof(int)) { |
| 577 *pid = result[0]; | 575 *pid = result[0]; |
| 578 } else if (bytes_read == 2 * sizeof(int)) { | 576 } else if (bytes_read == 2 * sizeof(int)) { |
| 579 *pid = result[0]; | 577 *pid = result[0]; |
| 580 child_errno = result[1]; | 578 child_errno = result[1]; |
| 581 SetOSErrorMessage(child_errno); | 579 ReadChildError(); |
| 582 return child_errno; | 580 return child_errno; |
| 583 } else if (bytes_read == -1) { | 581 } else if (bytes_read == -1) { |
| 584 return errno; | 582 return errno; |
| 585 } | 583 } |
| 586 return 0; | 584 return 0; |
| 587 } | 585 } |
| 588 | 586 |
| 589 | 587 |
| 590 void SetupDetached() { | 588 void SetupDetached() { |
| 591 ASSERT(mode_ == kDetached); | 589 ASSERT(mode_ == kDetached); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 // If CleanupAndReturnError is called without an actual errno make | 651 // If CleanupAndReturnError is called without an actual errno make |
| 654 // sure to return an error anyway. | 652 // sure to return an error anyway. |
| 655 if (actual_errno == 0) actual_errno = EPERM; | 653 if (actual_errno == 0) actual_errno = EPERM; |
| 656 SetChildOsErrorMessage(); | 654 SetChildOsErrorMessage(); |
| 657 CloseAllPipes(); | 655 CloseAllPipes(); |
| 658 return actual_errno; | 656 return actual_errno; |
| 659 } | 657 } |
| 660 | 658 |
| 661 | 659 |
| 662 void SetChildOsErrorMessage() { | 660 void SetChildOsErrorMessage() { |
| 663 SetOSErrorMessage(errno); | 661 const int kBufferSize = 1024; |
| 662 char error_message[kBufferSize]; |
| 663 strerror_r(errno, error_message, kBufferSize); |
| 664 *os_error_message_ = strdup(error_message); |
| 664 } | 665 } |
| 665 | 666 |
| 666 | 667 |
| 667 void ReportChildError() { | 668 void ReportChildError() { |
| 668 // In the case of failure in the child process write the errno to the exec | 669 // In the case of failure in the child process write the errno and |
| 669 // control pipe and exit. | 670 // the OS error message to the exec control pipe and exit. |
| 670 int child_errno = errno; | 671 int child_errno = errno; |
| 671 FDUtils::WriteToBlocking( | 672 const int kBufferSize = 1024; |
| 672 exec_control_[1], &child_errno, sizeof(child_errno)); | 673 char os_error_message[kBufferSize]; |
| 673 _exit(1); | 674 strerror_r(errno, os_error_message, kBufferSize); |
| 675 int bytes_written = |
| 676 FDUtils::WriteToBlocking( |
| 677 exec_control_[1], &child_errno, sizeof(child_errno)); |
| 678 if (bytes_written == sizeof(child_errno)) { |
| 679 FDUtils::WriteToBlocking( |
| 680 exec_control_[1], os_error_message, strlen(os_error_message) + 1); |
| 681 } |
| 682 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); |
| 683 exit(1); |
| 674 } | 684 } |
| 675 | 685 |
| 676 | 686 |
| 677 void ReportPid(int pid) { | 687 void ReportPid(int pid) { |
| 678 // In the case of starting a detached process the actual pid of that process | 688 // In the case of starting a detached process the actual pid of that process |
| 679 // is communicated using the exec control pipe. | 689 // is communicated using the exec control pipe. |
| 680 int bytes_written = | 690 int bytes_written = |
| 681 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid)); | 691 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid)); |
| 682 ASSERT(bytes_written == sizeof(int)); | 692 ASSERT(bytes_written == sizeof(int)); |
| 683 USE(bytes_written); | 693 USE(bytes_written); |
| 684 } | 694 } |
| 685 | 695 |
| 686 | 696 |
| 687 void SetOSErrorMessage(int child_errno) { | 697 void ReadChildError() { |
| 688 const int kBufferSize = 1024; | 698 const int kMaxMessageSize = 256; |
| 689 char error_message[kBufferSize]; | 699 char* message = static_cast<char*>(malloc(kMaxMessageSize)); |
| 690 strerror_r(child_errno, error_message, kBufferSize); | 700 if (message != NULL) { |
| 691 *os_error_message_ = strdup(error_message); | 701 FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize); |
| 702 message[kMaxMessageSize - 1] = '\0'; |
| 703 *os_error_message_ = message; |
| 704 } else { |
| 705 // Could not get error message. It will be NULL. |
| 706 ASSERT(*os_error_message_ == NULL); |
| 707 } |
| 692 } | 708 } |
| 693 | 709 |
| 694 | 710 |
| 695 void ClosePipe(int* fds) { | 711 void ClosePipe(int* fds) { |
| 696 for (int i = 0; i < 2; i++) { | 712 for (int i = 0; i < 2; i++) { |
| 697 if (fds[i] != -1) { | 713 if (fds[i] != -1) { |
| 698 VOID_TEMP_FAILURE_RETRY(close(fds[i])); | 714 VOID_TEMP_FAILURE_RETRY(close(fds[i])); |
| 699 fds[i] = -1; | 715 fds[i] = -1; |
| 700 } | 716 } |
| 701 } | 717 } |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 bzero(&act, sizeof(act)); | 1062 bzero(&act, sizeof(act)); |
| 1047 act.sa_handler = SIG_DFL; | 1063 act.sa_handler = SIG_DFL; |
| 1048 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1064 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
| 1049 } | 1065 } |
| 1050 } | 1066 } |
| 1051 | 1067 |
| 1052 } // namespace bin | 1068 } // namespace bin |
| 1053 } // namespace dart | 1069 } // namespace dart |
| 1054 | 1070 |
| 1055 #endif // defined(TARGET_OS_MACOS) | 1071 #endif // defined(TARGET_OS_MACOS) |
| OLD | NEW |