| 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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if defined(TARGET_OS_MACOS) | 8 #if defined(TARGET_OS_MACOS) |
| 9 | 9 |
| 10 #include "bin/process.h" | 10 #include "bin/process.h" |
| 11 | 11 |
| 12 #if !TARGET_OS_IOS | 12 #if !TARGET_OS_IOS |
| 13 #include <crt_externs.h> // NOLINT | 13 #include <crt_externs.h> // NOLINT |
| 14 #endif | 14 #endif |
| 15 #include <errno.h> // NOLINT | 15 #include <errno.h> // NOLINT |
| 16 #include <fcntl.h> // NOLINT | 16 #include <fcntl.h> // NOLINT |
| 17 #include <poll.h> // NOLINT | 17 #include <poll.h> // NOLINT |
| 18 #include <signal.h> // NOLINT | 18 #include <signal.h> // NOLINT |
| 19 #include <stdio.h> // NOLINT | 19 #include <stdio.h> // NOLINT |
| 20 #include <stdlib.h> // NOLINT | 20 #include <stdlib.h> // NOLINT |
| 21 #include <string.h> // NOLINT | 21 #include <string.h> // NOLINT |
| 22 #include <unistd.h> // NOLINT | 22 #include <unistd.h> // NOLINT |
| 23 | 23 |
| 24 #include "bin/dartutils.h" | 24 #include "bin/dartutils.h" |
| 25 #include "bin/fdutils.h" | 25 #include "bin/fdutils.h" |
| 26 #include "bin/lockers.h" | 26 #include "bin/lockers.h" |
| 27 #include "bin/log.h" | 27 #include "bin/log.h" |
| 28 #include "bin/thread.h" | 28 #include "bin/thread.h" |
| 29 | 29 |
| 30 #include "platform/signal_blocker.h" | 30 #include "platform/signal_blocker.h" |
| 31 #include "platform/utils.h" | 31 #include "platform/utils.h" |
| 32 | 32 |
| 33 namespace dart { | 33 namespace dart { |
| 34 namespace bin { | 34 namespace bin { |
| 35 | 35 |
| 36 int Process::global_exit_code_ = 0; | 36 int Process::global_exit_code_ = 0; |
| 37 Mutex* Process::global_exit_code_mutex_ = new Mutex(); | 37 Mutex* Process::global_exit_code_mutex_ = new Mutex(); |
| 38 Process::ExitHook Process::exit_hook_ = NULL; | 38 Process::ExitHook Process::exit_hook_ = NULL; |
| 39 | 39 |
| 40 // ProcessInfo is used to map a process id to the file descriptor for | 40 // ProcessInfo is used to map a process id to the file descriptor for |
| 41 // the pipe used to communicate the exit code of the process to Dart. | 41 // the pipe used to communicate the exit code of the process to Dart. |
| 42 // ProcessInfo objects are kept in the static singly-linked | 42 // ProcessInfo objects are kept in the static singly-linked |
| 43 // ProcessInfoList. | 43 // ProcessInfoList. |
| 44 class ProcessInfo { | 44 class ProcessInfo { |
| 45 public: | 45 public: |
| 46 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } | 46 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) {} |
| 47 ~ProcessInfo() { | 47 ~ProcessInfo() { |
| 48 int closed = TEMP_FAILURE_RETRY(close(fd_)); | 48 int closed = TEMP_FAILURE_RETRY(close(fd_)); |
| 49 if (closed != 0) { | 49 if (closed != 0) { |
| 50 FATAL("Failed to close process exit code pipe"); | 50 FATAL("Failed to close process exit code pipe"); |
| 51 } | 51 } |
| 52 } | 52 } |
| 53 pid_t pid() { return pid_; } | 53 pid_t pid() { return pid_; } |
| 54 intptr_t fd() { return fd_; } | 54 intptr_t fd() { return fd_; } |
| 55 ProcessInfo* next() { return next_; } | 55 ProcessInfo* next() { return next_; } |
| 56 void set_next(ProcessInfo* info) { next_ = info; } | 56 void set_next(ProcessInfo* info) { next_ = info; } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 int negative = 0; | 200 int negative = 0; |
| 201 if (WIFEXITED(status)) { | 201 if (WIFEXITED(status)) { |
| 202 exit_code = WEXITSTATUS(status); | 202 exit_code = WEXITSTATUS(status); |
| 203 } | 203 } |
| 204 if (WIFSIGNALED(status)) { | 204 if (WIFSIGNALED(status)) { |
| 205 exit_code = WTERMSIG(status); | 205 exit_code = WTERMSIG(status); |
| 206 negative = 1; | 206 negative = 1; |
| 207 } | 207 } |
| 208 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); | 208 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); |
| 209 if (exit_code_fd != 0) { | 209 if (exit_code_fd != 0) { |
| 210 int message[2] = { exit_code, negative }; | 210 int message[2] = {exit_code, negative}; |
| 211 ssize_t result = | 211 ssize_t result = |
| 212 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); | 212 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); |
| 213 // If the process has been closed, the read end of the exit | 213 // If the process has been closed, the read end of the exit |
| 214 // pipe has been closed. It is therefore not a problem that | 214 // pipe has been closed. It is therefore not a problem that |
| 215 // write fails with a broken pipe error. Other errors should | 215 // write fails with a broken pipe error. Other errors should |
| 216 // not happen. | 216 // not happen. |
| 217 if ((result != -1) && (result != sizeof(message))) { | 217 if ((result != -1) && (result != sizeof(message))) { |
| 218 FATAL("Failed to write entire process exit message"); | 218 FATAL("Failed to write entire process exit message"); |
| 219 } else if ((result == -1) && (errno != EPIPE)) { | 219 } else if ((result == -1) && (errno != EPIPE)) { |
| 220 FATAL1("Failed to write exit code: %d", errno); | 220 FATAL1("Failed to write exit code: %d", errno); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 return 0; | 555 return 0; |
| 556 } | 556 } |
| 557 | 557 |
| 558 | 558 |
| 559 int ReadExecResult() { | 559 int ReadExecResult() { |
| 560 int child_errno; | 560 int child_errno; |
| 561 int bytes_read = -1; | 561 int bytes_read = -1; |
| 562 // Read exec result from child. If no data is returned the exec was | 562 // Read exec result from child. If no data is returned the exec was |
| 563 // successful and the exec call closed the pipe. Otherwise the errno | 563 // successful and the exec call closed the pipe. Otherwise the errno |
| 564 // is written to the pipe. | 564 // is written to the pipe. |
| 565 bytes_read = FDUtils::ReadFromBlocking( | 565 bytes_read = FDUtils::ReadFromBlocking(exec_control_[0], &child_errno, |
| 566 exec_control_[0], &child_errno, sizeof(child_errno)); | 566 sizeof(child_errno)); |
| 567 if (bytes_read == sizeof(child_errno)) { | 567 if (bytes_read == sizeof(child_errno)) { |
| 568 ReadChildError(); | 568 ReadChildError(); |
| 569 return child_errno; | 569 return child_errno; |
| 570 } else if (bytes_read == -1) { | 570 } else if (bytes_read == -1) { |
| 571 return errno; | 571 return errno; |
| 572 } | 572 } |
| 573 return 0; | 573 return 0; |
| 574 } | 574 } |
| 575 | 575 |
| 576 | 576 |
| 577 int ReadDetachedExecResult(pid_t *pid) { | 577 int ReadDetachedExecResult(pid_t* pid) { |
| 578 int child_errno; | 578 int child_errno; |
| 579 int bytes_read = -1; | 579 int bytes_read = -1; |
| 580 // Read exec result from child. If only pid data is returned the exec was | 580 // Read exec result from child. If only pid data is returned the exec was |
| 581 // successful and the exec call closed the pipe. Otherwise the errno | 581 // successful and the exec call closed the pipe. Otherwise the errno |
| 582 // is written to the pipe as well. | 582 // is written to the pipe as well. |
| 583 int result[2]; | 583 int result[2]; |
| 584 bytes_read = | 584 bytes_read = |
| 585 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result)); | 585 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result)); |
| 586 if (bytes_read == sizeof(int)) { | 586 if (bytes_read == sizeof(int)) { |
| 587 *pid = result[0]; | 587 *pid = result[0]; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 | 630 |
| 631 void SetupDetachedWithStdio() { | 631 void SetupDetachedWithStdio() { |
| 632 // Close all open file descriptors except for | 632 // Close all open file descriptors except for |
| 633 // exec_control_[1], write_out_[0], read_in_[1] and | 633 // exec_control_[1], write_out_[0], read_in_[1] and |
| 634 // read_err_[1]. | 634 // read_err_[1]. |
| 635 int max_fds = sysconf(_SC_OPEN_MAX); | 635 int max_fds = sysconf(_SC_OPEN_MAX); |
| 636 if (max_fds == -1) { | 636 if (max_fds == -1) { |
| 637 max_fds = _POSIX_OPEN_MAX; | 637 max_fds = _POSIX_OPEN_MAX; |
| 638 } | 638 } |
| 639 for (int fd = 0; fd < max_fds; fd++) { | 639 for (int fd = 0; fd < max_fds; fd++) { |
| 640 if ((fd != exec_control_[1]) && | 640 if ((fd != exec_control_[1]) && (fd != write_out_[0]) && |
| 641 (fd != write_out_[0]) && | 641 (fd != read_in_[1]) && (fd != read_err_[1])) { |
| 642 (fd != read_in_[1]) && | |
| 643 (fd != read_err_[1])) { | |
| 644 VOID_TEMP_FAILURE_RETRY(close(fd)); | 642 VOID_TEMP_FAILURE_RETRY(close(fd)); |
| 645 } | 643 } |
| 646 } | 644 } |
| 647 | 645 |
| 648 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { | 646 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
| 649 ReportChildError(); | 647 ReportChildError(); |
| 650 } | 648 } |
| 651 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); | 649 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); |
| 652 | 650 |
| 653 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { | 651 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 683 } | 681 } |
| 684 | 682 |
| 685 | 683 |
| 686 void ReportChildError() { | 684 void ReportChildError() { |
| 687 // In the case of failure in the child process write the errno and | 685 // In the case of failure in the child process write the errno and |
| 688 // the OS error message to the exec control pipe and exit. | 686 // the OS error message to the exec control pipe and exit. |
| 689 int child_errno = errno; | 687 int child_errno = errno; |
| 690 const int kBufferSize = 1024; | 688 const int kBufferSize = 1024; |
| 691 char os_error_message[kBufferSize]; | 689 char os_error_message[kBufferSize]; |
| 692 Utils::StrError(errno, os_error_message, kBufferSize); | 690 Utils::StrError(errno, os_error_message, kBufferSize); |
| 693 int bytes_written = FDUtils::WriteToBlocking( | 691 int bytes_written = FDUtils::WriteToBlocking(exec_control_[1], &child_errno, |
| 694 exec_control_[1], &child_errno, sizeof(child_errno)); | 692 sizeof(child_errno)); |
| 695 if (bytes_written == sizeof(child_errno)) { | 693 if (bytes_written == sizeof(child_errno)) { |
| 696 FDUtils::WriteToBlocking( | 694 FDUtils::WriteToBlocking(exec_control_[1], os_error_message, |
| 697 exec_control_[1], os_error_message, strlen(os_error_message) + 1); | 695 strlen(os_error_message) + 1); |
| 698 } | 696 } |
| 699 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); | 697 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); |
| 700 exit(1); | 698 exit(1); |
| 701 } | 699 } |
| 702 | 700 |
| 703 | 701 |
| 704 void ReportPid(int pid) { | 702 void ReportPid(int pid) { |
| 705 // In the case of starting a detached process the actual pid of that process | 703 // In the case of starting a detached process the actual pid of that process |
| 706 // is communicated using the exec control pipe. | 704 // is communicated using the exec control pipe. |
| 707 int bytes_written = | 705 int bytes_written = |
| (...skipping 28 matching lines...) Expand all Loading... |
| 736 | 734 |
| 737 | 735 |
| 738 void CloseAllPipes() { | 736 void CloseAllPipes() { |
| 739 ClosePipe(exec_control_); | 737 ClosePipe(exec_control_); |
| 740 ClosePipe(read_in_); | 738 ClosePipe(read_in_); |
| 741 ClosePipe(read_err_); | 739 ClosePipe(read_err_); |
| 742 ClosePipe(write_out_); | 740 ClosePipe(write_out_); |
| 743 } | 741 } |
| 744 | 742 |
| 745 | 743 |
| 746 int read_in_[2]; // Pipe for stdout to child process. | 744 int read_in_[2]; // Pipe for stdout to child process. |
| 747 int read_err_[2]; // Pipe for stderr to child process. | 745 int read_err_[2]; // Pipe for stderr to child process. |
| 748 int write_out_[2]; // Pipe for stdin to child process. | 746 int write_out_[2]; // Pipe for stdin to child process. |
| 749 int exec_control_[2]; // Pipe to get the result from exec. | 747 int exec_control_[2]; // Pipe to get the result from exec. |
| 750 | 748 |
| 751 char** program_arguments_; | 749 char** program_arguments_; |
| 752 char** program_environment_; | 750 char** program_environment_; |
| 753 | 751 |
| 754 const char* path_; | 752 const char* path_; |
| 755 const char* working_directory_; | 753 const char* working_directory_; |
| 756 ProcessStartMode mode_; | 754 ProcessStartMode mode_; |
| 757 intptr_t* in_; | 755 intptr_t* in_; |
| 758 intptr_t* out_; | 756 intptr_t* out_; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 772 const char* working_directory, | 770 const char* working_directory, |
| 773 char* environment[], | 771 char* environment[], |
| 774 intptr_t environment_length, | 772 intptr_t environment_length, |
| 775 ProcessStartMode mode, | 773 ProcessStartMode mode, |
| 776 intptr_t* in, | 774 intptr_t* in, |
| 777 intptr_t* out, | 775 intptr_t* out, |
| 778 intptr_t* err, | 776 intptr_t* err, |
| 779 intptr_t* id, | 777 intptr_t* id, |
| 780 intptr_t* exit_event, | 778 intptr_t* exit_event, |
| 781 char** os_error_message) { | 779 char** os_error_message) { |
| 782 ProcessStarter starter(path, | 780 ProcessStarter starter(path, arguments, arguments_length, working_directory, |
| 783 arguments, | 781 environment, environment_length, mode, in, out, err, |
| 784 arguments_length, | 782 id, exit_event, os_error_message); |
| 785 working_directory, | |
| 786 environment, | |
| 787 environment_length, | |
| 788 mode, | |
| 789 in, | |
| 790 out, | |
| 791 err, | |
| 792 id, | |
| 793 exit_event, | |
| 794 os_error_message); | |
| 795 return starter.Start(); | 783 return starter.Start(); |
| 796 } | 784 } |
| 797 | 785 |
| 798 | 786 |
| 799 class BufferList: public BufferListBase { | 787 class BufferList : public BufferListBase { |
| 800 public: | 788 public: |
| 801 BufferList() {} | 789 BufferList() {} |
| 802 | 790 |
| 803 bool Read(int fd, intptr_t available) { | 791 bool Read(int fd, intptr_t available) { |
| 804 // Read all available bytes. | 792 // Read all available bytes. |
| 805 while (available > 0) { | 793 while (available > 0) { |
| 806 if (free_size_ == 0) { | 794 if (free_size_ == 0) { |
| 807 Allocate(); | 795 Allocate(); |
| 808 } | 796 } |
| 809 ASSERT(free_size_ > 0); | 797 ASSERT(free_size_ > 0); |
| 810 ASSERT(free_size_ <= kBufferSize); | 798 ASSERT(free_size_ <= kBufferSize); |
| 811 size_t block_size = dart::Utils::Minimum(free_size_, available); | 799 size_t block_size = dart::Utils::Minimum(free_size_, available); |
| 812 ssize_t bytes = TEMP_FAILURE_RETRY(read( | 800 ssize_t bytes = TEMP_FAILURE_RETRY( |
| 813 fd, | 801 read(fd, reinterpret_cast<void*>(FreeSpaceAddress()), block_size)); |
| 814 reinterpret_cast<void*>(FreeSpaceAddress()), | |
| 815 block_size)); | |
| 816 if (bytes < 0) { | 802 if (bytes < 0) { |
| 817 return false; | 803 return false; |
| 818 } | 804 } |
| 819 data_size_ += bytes; | 805 data_size_ += bytes; |
| 820 free_size_ -= bytes; | 806 free_size_ -= bytes; |
| 821 available -= bytes; | 807 available -= bytes; |
| 822 } | 808 } |
| 823 return true; | 809 return true; |
| 824 } | 810 } |
| 825 | 811 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 if (fds[i].fd == out) { | 871 if (fds[i].fd == out) { |
| 886 if (!out_data.Read(out, avail)) { | 872 if (!out_data.Read(out, avail)) { |
| 887 return CloseProcessBuffers(fds); | 873 return CloseProcessBuffers(fds); |
| 888 } | 874 } |
| 889 } else if (fds[i].fd == err) { | 875 } else if (fds[i].fd == err) { |
| 890 if (!err_data.Read(err, avail)) { | 876 if (!err_data.Read(err, avail)) { |
| 891 return CloseProcessBuffers(fds); | 877 return CloseProcessBuffers(fds); |
| 892 } | 878 } |
| 893 } else if (fds[i].fd == exit_event) { | 879 } else if (fds[i].fd == exit_event) { |
| 894 if (avail == 8) { | 880 if (avail == 8) { |
| 895 intptr_t b = TEMP_FAILURE_RETRY(read(fds[i].fd, | 881 intptr_t b = |
| 896 exit_code_data.bytes, 8)); | 882 TEMP_FAILURE_RETRY(read(fds[i].fd, exit_code_data.bytes, 8)); |
| 897 if (b != 8) { | 883 if (b != 8) { |
| 898 return CloseProcessBuffers(fds); | 884 return CloseProcessBuffers(fds); |
| 899 } | 885 } |
| 900 } | 886 } |
| 901 } else { | 887 } else { |
| 902 UNREACHABLE(); | 888 UNREACHABLE(); |
| 903 } | 889 } |
| 904 } | 890 } |
| 905 } | 891 } |
| 906 if (((fds[i].revents & POLLHUP) != 0) || | 892 if (((fds[i].revents & POLLHUP) != 0) || |
| (...skipping 18 matching lines...) Expand all Loading... |
| 925 exit_code = -exit_code; | 911 exit_code = -exit_code; |
| 926 } | 912 } |
| 927 result->set_exit_code(exit_code); | 913 result->set_exit_code(exit_code); |
| 928 | 914 |
| 929 return true; | 915 return true; |
| 930 } | 916 } |
| 931 | 917 |
| 932 | 918 |
| 933 static int SignalMap(intptr_t id) { | 919 static int SignalMap(intptr_t id) { |
| 934 switch (static_cast<ProcessSignals>(id)) { | 920 switch (static_cast<ProcessSignals>(id)) { |
| 935 case kSighup: return SIGHUP; | 921 case kSighup: |
| 936 case kSigint: return SIGINT; | 922 return SIGHUP; |
| 937 case kSigquit: return SIGQUIT; | 923 case kSigint: |
| 938 case kSigill: return SIGILL; | 924 return SIGINT; |
| 939 case kSigtrap: return SIGTRAP; | 925 case kSigquit: |
| 940 case kSigabrt: return SIGABRT; | 926 return SIGQUIT; |
| 941 case kSigbus: return SIGBUS; | 927 case kSigill: |
| 942 case kSigfpe: return SIGFPE; | 928 return SIGILL; |
| 943 case kSigkill: return SIGKILL; | 929 case kSigtrap: |
| 944 case kSigusr1: return SIGUSR1; | 930 return SIGTRAP; |
| 945 case kSigsegv: return SIGSEGV; | 931 case kSigabrt: |
| 946 case kSigusr2: return SIGUSR2; | 932 return SIGABRT; |
| 947 case kSigpipe: return SIGPIPE; | 933 case kSigbus: |
| 948 case kSigalrm: return SIGALRM; | 934 return SIGBUS; |
| 949 case kSigterm: return SIGTERM; | 935 case kSigfpe: |
| 950 case kSigchld: return SIGCHLD; | 936 return SIGFPE; |
| 951 case kSigcont: return SIGCONT; | 937 case kSigkill: |
| 952 case kSigstop: return SIGSTOP; | 938 return SIGKILL; |
| 953 case kSigtstp: return SIGTSTP; | 939 case kSigusr1: |
| 954 case kSigttin: return SIGTTIN; | 940 return SIGUSR1; |
| 955 case kSigttou: return SIGTTOU; | 941 case kSigsegv: |
| 956 case kSigurg: return SIGURG; | 942 return SIGSEGV; |
| 957 case kSigxcpu: return SIGXCPU; | 943 case kSigusr2: |
| 958 case kSigxfsz: return SIGXFSZ; | 944 return SIGUSR2; |
| 959 case kSigvtalrm: return SIGVTALRM; | 945 case kSigpipe: |
| 960 case kSigprof: return SIGPROF; | 946 return SIGPIPE; |
| 961 case kSigwinch: return SIGWINCH; | 947 case kSigalrm: |
| 962 case kSigpoll: return -1; | 948 return SIGALRM; |
| 963 case kSigsys: return SIGSYS; | 949 case kSigterm: |
| 950 return SIGTERM; |
| 951 case kSigchld: |
| 952 return SIGCHLD; |
| 953 case kSigcont: |
| 954 return SIGCONT; |
| 955 case kSigstop: |
| 956 return SIGSTOP; |
| 957 case kSigtstp: |
| 958 return SIGTSTP; |
| 959 case kSigttin: |
| 960 return SIGTTIN; |
| 961 case kSigttou: |
| 962 return SIGTTOU; |
| 963 case kSigurg: |
| 964 return SIGURG; |
| 965 case kSigxcpu: |
| 966 return SIGXCPU; |
| 967 case kSigxfsz: |
| 968 return SIGXFSZ; |
| 969 case kSigvtalrm: |
| 970 return SIGVTALRM; |
| 971 case kSigprof: |
| 972 return SIGPROF; |
| 973 case kSigwinch: |
| 974 return SIGWINCH; |
| 975 case kSigpoll: |
| 976 return -1; |
| 977 case kSigsys: |
| 978 return SIGSYS; |
| 964 } | 979 } |
| 965 return -1; | 980 return -1; |
| 966 } | 981 } |
| 967 | 982 |
| 968 | 983 |
| 969 bool Process::Kill(intptr_t id, int signal) { | 984 bool Process::Kill(intptr_t id, int signal) { |
| 970 return (TEMP_FAILURE_RETRY(kill(id, SignalMap(signal))) != -1); | 985 return (TEMP_FAILURE_RETRY(kill(id, SignalMap(signal))) != -1); |
| 971 } | 986 } |
| 972 | 987 |
| 973 | 988 |
| 974 void Process::TerminateExitCodeHandler() { | 989 void Process::TerminateExitCodeHandler() { |
| 975 ExitCodeHandler::TerminateExitCodeThread(); | 990 ExitCodeHandler::TerminateExitCodeThread(); |
| 976 } | 991 } |
| 977 | 992 |
| 978 | 993 |
| 979 intptr_t Process::CurrentProcessId() { | 994 intptr_t Process::CurrentProcessId() { |
| 980 return static_cast<intptr_t>(getpid()); | 995 return static_cast<intptr_t>(getpid()); |
| 981 } | 996 } |
| 982 | 997 |
| 983 | 998 |
| 984 static Mutex* signal_mutex = new Mutex(); | 999 static Mutex* signal_mutex = new Mutex(); |
| 985 static SignalInfo* signal_handlers = NULL; | 1000 static SignalInfo* signal_handlers = NULL; |
| 986 static const int kSignalsCount = 7; | 1001 static const int kSignalsCount = 7; |
| 987 static const int kSignals[kSignalsCount] = { | 1002 static const int kSignals[kSignalsCount] = { |
| 988 SIGHUP, | 1003 SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGWINCH, |
| 989 SIGINT, | 1004 SIGQUIT // Allow VMService to listen on SIGQUIT. |
| 990 SIGTERM, | |
| 991 SIGUSR1, | |
| 992 SIGUSR2, | |
| 993 SIGWINCH, | |
| 994 SIGQUIT // Allow VMService to listen on SIGQUIT. | |
| 995 }; | 1005 }; |
| 996 | 1006 |
| 997 | 1007 |
| 998 SignalInfo::~SignalInfo() { | 1008 SignalInfo::~SignalInfo() { |
| 999 VOID_TEMP_FAILURE_RETRY(close(fd_)); | 1009 VOID_TEMP_FAILURE_RETRY(close(fd_)); |
| 1000 } | 1010 } |
| 1001 | 1011 |
| 1002 | 1012 |
| 1003 static void SignalHandler(int signal) { | 1013 static void SignalHandler(int signal) { |
| 1004 MutexLocker lock(signal_mutex); | 1014 MutexLocker lock(signal_mutex); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1025 break; | 1035 break; |
| 1026 } | 1036 } |
| 1027 } | 1037 } |
| 1028 if (!found) { | 1038 if (!found) { |
| 1029 return -1; | 1039 return -1; |
| 1030 } | 1040 } |
| 1031 int fds[2]; | 1041 int fds[2]; |
| 1032 if (NO_RETRY_EXPECTED(pipe(fds)) != 0) { | 1042 if (NO_RETRY_EXPECTED(pipe(fds)) != 0) { |
| 1033 return -1; | 1043 return -1; |
| 1034 } | 1044 } |
| 1035 if (!FDUtils::SetCloseOnExec(fds[0]) || | 1045 if (!FDUtils::SetCloseOnExec(fds[0]) || !FDUtils::SetCloseOnExec(fds[1]) || |
| 1036 !FDUtils::SetCloseOnExec(fds[1]) || | |
| 1037 !FDUtils::SetNonBlocking(fds[0])) { | 1046 !FDUtils::SetNonBlocking(fds[0])) { |
| 1038 VOID_TEMP_FAILURE_RETRY(close(fds[0])); | 1047 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
| 1039 VOID_TEMP_FAILURE_RETRY(close(fds[1])); | 1048 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
| 1040 return -1; | 1049 return -1; |
| 1041 } | 1050 } |
| 1042 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 1051 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
| 1043 MutexLocker lock(signal_mutex); | 1052 MutexLocker lock(signal_mutex); |
| 1044 SignalInfo* handler = signal_handlers; | 1053 SignalInfo* handler = signal_handlers; |
| 1045 bool listen = true; | 1054 bool listen = true; |
| 1046 while (handler != NULL) { | 1055 while (handler != NULL) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1105 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1114 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
| 1106 } | 1115 } |
| 1107 } | 1116 } |
| 1108 | 1117 |
| 1109 } // namespace bin | 1118 } // namespace bin |
| 1110 } // namespace dart | 1119 } // namespace dart |
| 1111 | 1120 |
| 1112 #endif // defined(TARGET_OS_MACOS) | 1121 #endif // defined(TARGET_OS_MACOS) |
| 1113 | 1122 |
| 1114 #endif // !defined(DART_IO_DISABLED) | 1123 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |