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 |