| 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_ANDROID) | 6 #if defined(TARGET_OS_ANDROID) |
| 7 | 7 |
| 8 #include "bin/process.h" | 8 #include "bin/process.h" |
| 9 | 9 |
| 10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
| 11 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
| 12 #include <poll.h> // NOLINT | 12 #include <poll.h> // NOLINT |
| 13 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
| 14 #include <stdlib.h> // NOLINT | 14 #include <stdlib.h> // NOLINT |
| 15 #include <string.h> // NOLINT | 15 #include <string.h> // NOLINT |
| 16 #include <sys/wait.h> // NOLINT | 16 #include <sys/wait.h> // NOLINT |
| 17 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
| 18 | 18 |
| 19 #include "bin/dartutils.h" | 19 #include "bin/dartutils.h" |
| 20 #include "bin/fdutils.h" | 20 #include "bin/fdutils.h" |
| 21 #include "bin/lockers.h" | 21 #include "bin/lockers.h" |
| 22 #include "bin/log.h" | 22 #include "bin/log.h" |
| 23 #include "bin/thread.h" | 23 #include "bin/thread.h" |
| 24 | 24 |
| 25 #include "platform/signal_blocker.h" | 25 #include "platform/signal_blocker.h" |
| 26 #include "platform/utils.h" | 26 #include "platform/utils.h" |
| 27 | 27 |
| 28 | |
| 29 extern char **environ; | 28 extern char **environ; |
| 30 | 29 |
| 31 | |
| 32 namespace dart { | 30 namespace dart { |
| 33 namespace bin { | 31 namespace bin { |
| 34 | 32 |
| 35 // ProcessInfo is used to map a process id to the file descriptor for | 33 // ProcessInfo is used to map a process id to the file descriptor for |
| 36 // the pipe used to communicate the exit code of the process to Dart. | 34 // the pipe used to communicate the exit code of the process to Dart. |
| 37 // ProcessInfo objects are kept in the static singly-linked | 35 // ProcessInfo objects are kept in the static singly-linked |
| 38 // ProcessInfoList. | 36 // ProcessInfoList. |
| 39 class ProcessInfo { | 37 class ProcessInfo { |
| 40 public: | 38 public: |
| 41 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } | 39 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } |
| 42 ~ProcessInfo() { | 40 ~ProcessInfo() { |
| 43 int closed = TEMP_FAILURE_RETRY(close(fd_)); | 41 int closed = TEMP_FAILURE_RETRY(close(fd_)); |
| 44 if (closed != 0) { | 42 if (closed != 0) { |
| 45 FATAL("Failed to close process exit code pipe"); | 43 FATAL("Failed to close process exit code pipe"); |
| 46 } | 44 } |
| 47 } | 45 } |
| 48 pid_t pid() { return pid_; } | 46 pid_t pid() { return pid_; } |
| 49 intptr_t fd() { return fd_; } | 47 intptr_t fd() { return fd_; } |
| 50 ProcessInfo* next() { return next_; } | 48 ProcessInfo* next() { return next_; } |
| 51 void set_next(ProcessInfo* info) { next_ = info; } | 49 void set_next(ProcessInfo* info) { next_ = info; } |
| 52 | 50 |
| 53 private: | 51 private: |
| 54 pid_t pid_; | 52 pid_t pid_; |
| 55 intptr_t fd_; | 53 intptr_t fd_; |
| 56 ProcessInfo* next_; | 54 ProcessInfo* next_; |
| 55 |
| 56 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); |
| 57 }; | 57 }; |
| 58 | 58 |
| 59 | 59 |
| 60 // Singly-linked list of ProcessInfo objects for all active processes | 60 // Singly-linked list of ProcessInfo objects for all active processes |
| 61 // started from Dart. | 61 // started from Dart. |
| 62 class ProcessInfoList { | 62 class ProcessInfoList { |
| 63 public: | 63 public: |
| 64 static void AddProcess(pid_t pid, intptr_t fd) { | 64 static void AddProcess(pid_t pid, intptr_t fd) { |
| 65 MutexLocker locker(mutex_); | 65 MutexLocker locker(mutex_); |
| 66 ProcessInfo* info = new ProcessInfo(pid, fd); | 66 ProcessInfo* info = new ProcessInfo(pid, fd); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 private: | 104 private: |
| 105 // Linked list of ProcessInfo objects for all active processes | 105 // Linked list of ProcessInfo objects for all active processes |
| 106 // started from Dart code. | 106 // started from Dart code. |
| 107 static ProcessInfo* active_processes_; | 107 static ProcessInfo* active_processes_; |
| 108 // Mutex protecting all accesses to the linked list of active | 108 // Mutex protecting all accesses to the linked list of active |
| 109 // processes. | 109 // processes. |
| 110 static Mutex* mutex_; | 110 static Mutex* mutex_; |
| 111 |
| 112 DISALLOW_ALLOCATION(); |
| 113 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); |
| 111 }; | 114 }; |
| 112 | 115 |
| 113 | 116 |
| 114 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 117 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
| 115 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 118 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
| 116 | 119 |
| 117 | 120 |
| 118 // The exit code handler sets up a separate thread which waits for child | 121 // The exit code handler sets up a separate thread which waits for child |
| 119 // processes to terminate. That separate thread can then get the exit code from | 122 // processes to terminate. That separate thread can then get the exit code from |
| 120 // processes that have exited and communicate it to Dart through the | 123 // processes that have exited and communicate it to Dart through the |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 | 171 |
| 169 private: | 172 private: |
| 170 // Entry point for the separate exit code handler thread started by | 173 // Entry point for the separate exit code handler thread started by |
| 171 // the ExitCodeHandler. | 174 // the ExitCodeHandler. |
| 172 static void ExitCodeHandlerEntry(uword param) { | 175 static void ExitCodeHandlerEntry(uword param) { |
| 173 pid_t pid = 0; | 176 pid_t pid = 0; |
| 174 int status = 0; | 177 int status = 0; |
| 175 while (true) { | 178 while (true) { |
| 176 { | 179 { |
| 177 MonitorLocker locker(monitor_); | 180 MonitorLocker locker(monitor_); |
| 178 while (running_ && process_count_ == 0) { | 181 while (running_ && (process_count_ == 0)) { |
| 179 monitor_->Wait(Monitor::kNoTimeout); | 182 monitor_->Wait(Monitor::kNoTimeout); |
| 180 } | 183 } |
| 181 if (!running_) { | 184 if (!running_) { |
| 182 terminate_done_ = true; | 185 terminate_done_ = true; |
| 183 monitor_->Notify(); | 186 monitor_->Notify(); |
| 184 return; | 187 return; |
| 185 } | 188 } |
| 186 } | 189 } |
| 187 | 190 |
| 188 if ((pid = TEMP_FAILURE_RETRY(wait(&status))) > 0) { | 191 if ((pid = TEMP_FAILURE_RETRY(wait(&status))) > 0) { |
| 189 int exit_code = 0; | 192 int exit_code = 0; |
| 190 int negative = 0; | 193 int negative = 0; |
| 191 if (WIFEXITED(status)) { | 194 if (WIFEXITED(status)) { |
| 192 exit_code = WEXITSTATUS(status); | 195 exit_code = WEXITSTATUS(status); |
| 193 } | 196 } |
| 194 if (WIFSIGNALED(status)) { | 197 if (WIFSIGNALED(status)) { |
| 195 exit_code = WTERMSIG(status); | 198 exit_code = WTERMSIG(status); |
| 196 negative = 1; | 199 negative = 1; |
| 197 } | 200 } |
| 198 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); | 201 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); |
| 199 if (exit_code_fd != 0) { | 202 if (exit_code_fd != 0) { |
| 200 int message[2] = { exit_code, negative }; | 203 int message[2] = { exit_code, negative }; |
| 201 ssize_t result = | 204 ssize_t result = |
| 202 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); | 205 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); |
| 203 // If the process has been closed, the read end of the exit | 206 // If the process has been closed, the read end of the exit |
| 204 // pipe has been closed. It is therefore not a problem that | 207 // pipe has been closed. It is therefore not a problem that |
| 205 // write fails with a broken pipe error. Other errors should | 208 // write fails with a broken pipe error. Other errors should |
| 206 // not happen. | 209 // not happen. |
| 207 if (result != -1 && result != sizeof(message)) { | 210 if ((result != -1) && (result != sizeof(message))) { |
| 208 FATAL("Failed to write entire process exit message"); | 211 FATAL("Failed to write entire process exit message"); |
| 209 } else if (result == -1 && errno != EPIPE) { | 212 } else if ((result == -1) && (errno != EPIPE)) { |
| 210 FATAL1("Failed to write exit code: %d", errno); | 213 FATAL1("Failed to write exit code: %d", errno); |
| 211 } | 214 } |
| 212 ProcessInfoList::RemoveProcess(pid); | 215 ProcessInfoList::RemoveProcess(pid); |
| 213 { | 216 { |
| 214 MonitorLocker locker(monitor_); | 217 MonitorLocker locker(monitor_); |
| 215 process_count_--; | 218 process_count_--; |
| 216 } | 219 } |
| 217 } | 220 } |
| 218 } | 221 } |
| 219 } | 222 } |
| 220 } | 223 } |
| 221 | 224 |
| 222 static bool terminate_done_; | 225 static bool terminate_done_; |
| 223 static int process_count_; | 226 static int process_count_; |
| 224 static bool running_; | 227 static bool running_; |
| 225 static Monitor* monitor_; | 228 static Monitor* monitor_; |
| 229 |
| 230 DISALLOW_ALLOCATION(); |
| 231 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); |
| 226 }; | 232 }; |
| 227 | 233 |
| 228 | 234 |
| 229 bool ExitCodeHandler::running_ = false; | 235 bool ExitCodeHandler::running_ = false; |
| 230 int ExitCodeHandler::process_count_ = 0; | 236 int ExitCodeHandler::process_count_ = 0; |
| 231 bool ExitCodeHandler::terminate_done_ = false; | 237 bool ExitCodeHandler::terminate_done_ = false; |
| 232 Monitor* ExitCodeHandler::monitor_ = new Monitor(); | 238 Monitor* ExitCodeHandler::monitor_ = new Monitor(); |
| 233 | 239 |
| 234 | 240 |
| 235 class ProcessStarter { | 241 class ProcessStarter { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 258 os_error_message_(os_error_message) { | 264 os_error_message_(os_error_message) { |
| 259 read_in_[0] = -1; | 265 read_in_[0] = -1; |
| 260 read_in_[1] = -1; | 266 read_in_[1] = -1; |
| 261 read_err_[0] = -1; | 267 read_err_[0] = -1; |
| 262 read_err_[1] = -1; | 268 read_err_[1] = -1; |
| 263 write_out_[0] = -1; | 269 write_out_[0] = -1; |
| 264 write_out_[1] = -1; | 270 write_out_[1] = -1; |
| 265 exec_control_[0] = -1; | 271 exec_control_[0] = -1; |
| 266 exec_control_[1] = -1; | 272 exec_control_[1] = -1; |
| 267 | 273 |
| 268 program_arguments_ = new char*[arguments_length + 2]; | 274 program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate( |
| 275 (arguments_length + 2) * sizeof(*program_arguments_))); |
| 269 program_arguments_[0] = const_cast<char*>(path_); | 276 program_arguments_[0] = const_cast<char*>(path_); |
| 270 for (int i = 0; i < arguments_length; i++) { | 277 for (int i = 0; i < arguments_length; i++) { |
| 271 program_arguments_[i + 1] = arguments[i]; | 278 program_arguments_[i + 1] = arguments[i]; |
| 272 } | 279 } |
| 273 program_arguments_[arguments_length + 1] = NULL; | 280 program_arguments_[arguments_length + 1] = NULL; |
| 274 | 281 |
| 275 program_environment_ = NULL; | 282 program_environment_ = NULL; |
| 276 if (environment != NULL) { | 283 if (environment != NULL) { |
| 277 program_environment_ = new char*[environment_length + 1]; | 284 program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate( |
| 285 (environment_length + 1) * sizeof(*program_environment_))); |
| 278 for (int i = 0; i < environment_length; i++) { | 286 for (int i = 0; i < environment_length; i++) { |
| 279 program_environment_[i] = environment[i]; | 287 program_environment_[i] = environment[i]; |
| 280 } | 288 } |
| 281 program_environment_[environment_length] = NULL; | 289 program_environment_[environment_length] = NULL; |
| 282 } | 290 } |
| 283 } | 291 } |
| 284 | 292 |
| 285 | 293 |
| 286 ~ProcessStarter() { | |
| 287 delete[] program_arguments_; | |
| 288 delete[] program_environment_; | |
| 289 } | |
| 290 | |
| 291 | |
| 292 int Start() { | 294 int Start() { |
| 293 // Create pipes required. | 295 // Create pipes required. |
| 294 int err = CreatePipes(); | 296 int err = CreatePipes(); |
| 295 if (err != 0) return err; | 297 if (err != 0) { |
| 298 return err; |
| 299 } |
| 296 | 300 |
| 297 // Fork to create the new process. | 301 // Fork to create the new process. |
| 298 pid_t pid = TEMP_FAILURE_RETRY(fork()); | 302 pid_t pid = TEMP_FAILURE_RETRY(fork()); |
| 299 if (pid < 0) { | 303 if (pid < 0) { |
| 300 // Failed to fork. | 304 // Failed to fork. |
| 301 return CleanupAndReturnError(); | 305 return CleanupAndReturnError(); |
| 302 } else if (pid == 0) { | 306 } else if (pid == 0) { |
| 303 // This runs in the new process. | 307 // This runs in the new process. |
| 304 NewProcess(); | 308 NewProcess(); |
| 305 } | 309 } |
| 306 | 310 |
| 307 // This runs in the original process. | 311 // This runs in the original process. |
| 308 | 312 |
| 309 // Be sure to listen for exit-codes, now we have a child-process. | 313 // Be sure to listen for exit-codes, now we have a child-process. |
| 310 ExitCodeHandler::ProcessStarted(); | 314 ExitCodeHandler::ProcessStarted(); |
| 311 | 315 |
| 312 // Register the child process if not detached. | 316 // Register the child process if not detached. |
| 313 if (mode_ == kNormal) { | 317 if (mode_ == kNormal) { |
| 314 err = RegisterProcess(pid); | 318 err = RegisterProcess(pid); |
| 315 if (err != 0) return err; | 319 if (err != 0) { |
| 320 return err; |
| 321 } |
| 316 } | 322 } |
| 317 | 323 |
| 318 // Notify child process to start. This is done to delay the call to exec | 324 // Notify child process to start. This is done to delay the call to exec |
| 319 // until the process is registered above, and we are ready to receive the | 325 // until the process is registered above, and we are ready to receive the |
| 320 // exit code. | 326 // exit code. |
| 321 char msg = '1'; | 327 char msg = '1'; |
| 322 int bytes_written = | 328 int bytes_written = |
| 323 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg)); | 329 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg)); |
| 324 if (bytes_written != sizeof(msg)) { | 330 if (bytes_written != sizeof(msg)) { |
| 325 return CleanupAndReturnError(); | 331 return CleanupAndReturnError(); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 pid = TEMP_FAILURE_RETRY(fork()); | 490 pid = TEMP_FAILURE_RETRY(fork()); |
| 485 if (pid < 0) { | 491 if (pid < 0) { |
| 486 ReportChildError(); | 492 ReportChildError(); |
| 487 } else if (pid == 0) { | 493 } else if (pid == 0) { |
| 488 if (mode_ == kDetached) { | 494 if (mode_ == kDetached) { |
| 489 SetupDetached(); | 495 SetupDetached(); |
| 490 } else { | 496 } else { |
| 491 SetupDetachedWithStdio(); | 497 SetupDetachedWithStdio(); |
| 492 } | 498 } |
| 493 | 499 |
| 494 if (working_directory_ != NULL && | 500 if ((working_directory_ != NULL) && |
| 495 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 501 (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) { |
| 496 ReportChildError(); | 502 ReportChildError(); |
| 497 } | 503 } |
| 498 | 504 |
| 499 // Report the final PID and do the exec. | 505 // Report the final PID and do the exec. |
| 500 ReportPid(getpid()); // getpid cannot fail. | 506 ReportPid(getpid()); // getpid cannot fail. |
| 501 VOID_TEMP_FAILURE_RETRY( | 507 VOID_TEMP_FAILURE_RETRY( |
| 502 execvp(path_, const_cast<char* const*>(program_arguments_))); | 508 execvp(path_, const_cast<char* const*>(program_arguments_))); |
| 503 ReportChildError(); | 509 ReportChildError(); |
| 504 } else { | 510 } else { |
| 505 // Exit the intermeiate process. | 511 // Exit the intermeiate process. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 527 return 0; | 533 return 0; |
| 528 } | 534 } |
| 529 | 535 |
| 530 | 536 |
| 531 int ReadExecResult() { | 537 int ReadExecResult() { |
| 532 int child_errno; | 538 int child_errno; |
| 533 int bytes_read = -1; | 539 int bytes_read = -1; |
| 534 // Read exec result from child. If no data is returned the exec was | 540 // Read exec result from child. If no data is returned the exec was |
| 535 // successful and the exec call closed the pipe. Otherwise the errno | 541 // successful and the exec call closed the pipe. Otherwise the errno |
| 536 // is written to the pipe. | 542 // is written to the pipe. |
| 537 bytes_read = | 543 bytes_read = FDUtils::ReadFromBlocking( |
| 538 FDUtils::ReadFromBlocking( | 544 exec_control_[0], &child_errno, sizeof(child_errno)); |
| 539 exec_control_[0], &child_errno, sizeof(child_errno)); | |
| 540 if (bytes_read == sizeof(child_errno)) { | 545 if (bytes_read == sizeof(child_errno)) { |
| 541 ReadChildError(); | 546 ReadChildError(); |
| 542 return child_errno; | 547 return child_errno; |
| 543 } else if (bytes_read == -1) { | 548 } else if (bytes_read == -1) { |
| 544 return errno; | 549 return errno; |
| 545 } | 550 } |
| 546 return 0; | 551 return 0; |
| 547 } | 552 } |
| 548 | 553 |
| 549 | 554 |
| 550 int ReadDetachedExecResult(pid_t *pid) { | 555 int ReadDetachedExecResult(pid_t *pid) { |
| 551 int child_errno; | 556 int child_errno; |
| 552 int bytes_read = -1; | 557 int bytes_read = -1; |
| 553 // Read exec result from child. If only pid data is returned the exec was | 558 // Read exec result from child. If only pid data is returned the exec was |
| 554 // successful and the exec call closed the pipe. Otherwise the errno | 559 // successful and the exec call closed the pipe. Otherwise the errno |
| 555 // is written to the pipe as well. | 560 // is written to the pipe as well. |
| 556 int result[2]; | 561 int result[2]; |
| 557 bytes_read = | 562 bytes_read = |
| 558 FDUtils::ReadFromBlocking( | 563 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result)); |
| 559 exec_control_[0], result, sizeof(result)); | |
| 560 if (bytes_read == sizeof(int)) { | 564 if (bytes_read == sizeof(int)) { |
| 561 *pid = result[0]; | 565 *pid = result[0]; |
| 562 } else if (bytes_read == 2 * sizeof(int)) { | 566 } else if (bytes_read == 2 * sizeof(int)) { |
| 563 *pid = result[0]; | 567 *pid = result[0]; |
| 564 child_errno = result[1]; | 568 child_errno = result[1]; |
| 565 ReadChildError(); | 569 ReadChildError(); |
| 566 return child_errno; | 570 return child_errno; |
| 567 } else if (bytes_read == -1) { | 571 } else if (bytes_read == -1) { |
| 568 return errno; | 572 return errno; |
| 569 } | 573 } |
| 570 return 0; | 574 return 0; |
| 571 } | 575 } |
| 572 | 576 |
| 573 | 577 |
| 574 void SetupDetached() { | 578 void SetupDetached() { |
| 575 ASSERT(mode_ == kDetached); | 579 ASSERT(mode_ == kDetached); |
| 576 | 580 |
| 577 // Close all open file descriptors except for exec_control_[1]. | 581 // Close all open file descriptors except for exec_control_[1]. |
| 578 int max_fds = sysconf(_SC_OPEN_MAX); | 582 int max_fds = sysconf(_SC_OPEN_MAX); |
| 579 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; | 583 if (max_fds == -1) { |
| 584 max_fds = _POSIX_OPEN_MAX; |
| 585 } |
| 580 for (int fd = 0; fd < max_fds; fd++) { | 586 for (int fd = 0; fd < max_fds; fd++) { |
| 581 if (fd != exec_control_[1]) { | 587 if (fd != exec_control_[1]) { |
| 582 VOID_TEMP_FAILURE_RETRY(close(fd)); | 588 VOID_TEMP_FAILURE_RETRY(close(fd)); |
| 583 } | 589 } |
| 584 } | 590 } |
| 585 | 591 |
| 586 // Re-open stdin, stdout and stderr and connect them to /dev/null. | 592 // Re-open stdin, stdout and stderr and connect them to /dev/null. |
| 587 // The loop above should already have closed all of them, so | 593 // The loop above should already have closed all of them, so |
| 588 // creating new file descriptors should start at STDIN_FILENO. | 594 // creating new file descriptors should start at STDIN_FILENO. |
| 589 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); | 595 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); |
| 590 if (fd != STDIN_FILENO) { | 596 if (fd != STDIN_FILENO) { |
| 591 ReportChildError(); | 597 ReportChildError(); |
| 592 } | 598 } |
| 593 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != | 599 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != |
| 594 STDOUT_FILENO) { | 600 STDOUT_FILENO) { |
| 595 ReportChildError(); | 601 ReportChildError(); |
| 596 } | 602 } |
| 597 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != | 603 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != |
| 598 STDERR_FILENO) { | 604 STDERR_FILENO) { |
| 599 ReportChildError(); | 605 ReportChildError(); |
| 600 } | 606 } |
| 601 } | 607 } |
| 602 | 608 |
| 603 void SetupDetachedWithStdio() { | 609 void SetupDetachedWithStdio() { |
| 604 // Close all open file descriptors except for | 610 // Close all open file descriptors except for |
| 605 // exec_control_[1], write_out_[0], read_in_[1] and | 611 // exec_control_[1], write_out_[0], read_in_[1] and |
| 606 // read_err_[1]. | 612 // read_err_[1]. |
| 607 int max_fds = sysconf(_SC_OPEN_MAX); | 613 int max_fds = sysconf(_SC_OPEN_MAX); |
| 608 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; | 614 if (max_fds == -1) { |
| 615 max_fds = _POSIX_OPEN_MAX; |
| 616 } |
| 609 for (int fd = 0; fd < max_fds; fd++) { | 617 for (int fd = 0; fd < max_fds; fd++) { |
| 610 if (fd != exec_control_[1] && | 618 if ((fd != exec_control_[1]) && |
| 611 fd != write_out_[0] && | 619 (fd != write_out_[0]) && |
| 612 fd != read_in_[1] && | 620 (fd != read_in_[1]) && |
| 613 fd != read_err_[1]) { | 621 (fd != read_err_[1])) { |
| 614 VOID_TEMP_FAILURE_RETRY(close(fd)); | 622 VOID_TEMP_FAILURE_RETRY(close(fd)); |
| 615 } | 623 } |
| 616 } | 624 } |
| 617 | 625 |
| 618 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { | 626 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
| 619 ReportChildError(); | 627 ReportChildError(); |
| 620 } | 628 } |
| 621 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); | 629 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); |
| 622 | 630 |
| 623 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { | 631 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 | 732 |
| 725 const char* path_; | 733 const char* path_; |
| 726 const char* working_directory_; | 734 const char* working_directory_; |
| 727 ProcessStartMode mode_; | 735 ProcessStartMode mode_; |
| 728 intptr_t* in_; | 736 intptr_t* in_; |
| 729 intptr_t* out_; | 737 intptr_t* out_; |
| 730 intptr_t* err_; | 738 intptr_t* err_; |
| 731 intptr_t* id_; | 739 intptr_t* id_; |
| 732 intptr_t* exit_event_; | 740 intptr_t* exit_event_; |
| 733 char** os_error_message_; | 741 char** os_error_message_; |
| 742 |
| 743 DISALLOW_ALLOCATION(); |
| 744 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); |
| 734 }; | 745 }; |
| 735 | 746 |
| 736 | 747 |
| 737 int Process::Start(const char* path, | 748 int Process::Start(const char* path, |
| 738 char* arguments[], | 749 char* arguments[], |
| 739 intptr_t arguments_length, | 750 intptr_t arguments_length, |
| 740 const char* working_directory, | 751 const char* working_directory, |
| 741 char* environment[], | 752 char* environment[], |
| 742 intptr_t environment_length, | 753 intptr_t environment_length, |
| 743 ProcessStartMode mode, | 754 ProcessStartMode mode, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 759 err, | 770 err, |
| 760 id, | 771 id, |
| 761 exit_event, | 772 exit_event, |
| 762 os_error_message); | 773 os_error_message); |
| 763 return starter.Start(); | 774 return starter.Start(); |
| 764 } | 775 } |
| 765 | 776 |
| 766 | 777 |
| 767 class BufferList: public BufferListBase { | 778 class BufferList: public BufferListBase { |
| 768 public: | 779 public: |
| 780 BufferList() {} |
| 781 |
| 769 bool Read(int fd, intptr_t available) { | 782 bool Read(int fd, intptr_t available) { |
| 770 // Read all available bytes. | 783 // Read all available bytes. |
| 771 while (available > 0) { | 784 while (available > 0) { |
| 772 if (free_size_ == 0) Allocate(); | 785 if (free_size_ == 0) { |
| 786 Allocate(); |
| 787 } |
| 773 ASSERT(free_size_ > 0); | 788 ASSERT(free_size_ > 0); |
| 774 ASSERT(free_size_ <= kBufferSize); | 789 ASSERT(free_size_ <= kBufferSize); |
| 775 intptr_t block_size = dart::Utils::Minimum(free_size_, available); | 790 intptr_t block_size = dart::Utils::Minimum(free_size_, available); |
| 776 intptr_t bytes = TEMP_FAILURE_RETRY(read( | 791 intptr_t bytes = TEMP_FAILURE_RETRY(read( |
| 777 fd, | 792 fd, |
| 778 reinterpret_cast<void*>(FreeSpaceAddress()), | 793 reinterpret_cast<void*>(FreeSpaceAddress()), |
| 779 block_size)); | 794 block_size)); |
| 780 if (bytes < 0) return false; | 795 if (bytes < 0) { |
| 796 return false; |
| 797 } |
| 781 data_size_ += bytes; | 798 data_size_ += bytes; |
| 782 free_size_ -= bytes; | 799 free_size_ -= bytes; |
| 783 available -= bytes; | 800 available -= bytes; |
| 784 } | 801 } |
| 785 return true; | 802 return true; |
| 786 } | 803 } |
| 804 |
| 805 private: |
| 806 DISALLOW_COPY_AND_ASSIGN(BufferList); |
| 787 }; | 807 }; |
| 788 | 808 |
| 789 | 809 |
| 790 static bool CloseProcessBuffers(struct pollfd fds[3]) { | 810 static bool CloseProcessBuffers(struct pollfd fds[3]) { |
| 791 int e = errno; | 811 int e = errno; |
| 792 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); | 812 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); |
| 793 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); | 813 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); |
| 794 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); | 814 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); |
| 795 errno = e; | 815 errno = e; |
| 796 return false; | 816 return false; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 int alive = 3; | 848 int alive = 3; |
| 829 while (alive > 0) { | 849 while (alive > 0) { |
| 830 // Blocking call waiting for events from the child process. | 850 // Blocking call waiting for events from the child process. |
| 831 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { | 851 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { |
| 832 return CloseProcessBuffers(fds); | 852 return CloseProcessBuffers(fds); |
| 833 } | 853 } |
| 834 | 854 |
| 835 // Process incoming data. | 855 // Process incoming data. |
| 836 int current_alive = alive; | 856 int current_alive = alive; |
| 837 for (int i = 0; i < current_alive; i++) { | 857 for (int i = 0; i < current_alive; i++) { |
| 838 if (fds[i].revents & POLLIN) { | 858 if ((fds[i].revents & POLLIN) != 0) { |
| 839 intptr_t avail = FDUtils::AvailableBytes(fds[i].fd); | 859 intptr_t avail = FDUtils::AvailableBytes(fds[i].fd); |
| 840 if (fds[i].fd == out) { | 860 if (fds[i].fd == out) { |
| 841 if (!out_data.Read(out, avail)) { | 861 if (!out_data.Read(out, avail)) { |
| 842 return CloseProcessBuffers(fds); | 862 return CloseProcessBuffers(fds); |
| 843 } | 863 } |
| 844 } else if (fds[i].fd == err) { | 864 } else if (fds[i].fd == err) { |
| 845 if (!err_data.Read(err, avail)) { | 865 if (!err_data.Read(err, avail)) { |
| 846 return CloseProcessBuffers(fds); | 866 return CloseProcessBuffers(fds); |
| 847 } | 867 } |
| 848 } else if (fds[i].fd == exit_event) { | 868 } else if (fds[i].fd == exit_event) { |
| 849 if (avail == 8) { | 869 if (avail == 8) { |
| 850 intptr_t b = TEMP_FAILURE_RETRY(read(exit_event, | 870 intptr_t b = TEMP_FAILURE_RETRY(read(exit_event, |
| 851 exit_code_data.bytes, 8)); | 871 exit_code_data.bytes, 8)); |
| 852 if (b != 8) { | 872 if (b != 8) { |
| 853 return CloseProcessBuffers(fds); | 873 return CloseProcessBuffers(fds); |
| 854 } | 874 } |
| 855 } | 875 } |
| 856 } else { | 876 } else { |
| 857 UNREACHABLE(); | 877 UNREACHABLE(); |
| 858 } | 878 } |
| 859 } | 879 } |
| 860 if (fds[i].revents & POLLHUP) { | 880 if ((fds[i].revents & POLLHUP) != 0) { |
| 861 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); | 881 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); |
| 862 alive--; | 882 alive--; |
| 863 if (i < alive) { | 883 if (i < alive) { |
| 864 fds[i] = fds[alive]; | 884 fds[i] = fds[alive]; |
| 865 } | 885 } |
| 866 } | 886 } |
| 867 } | 887 } |
| 868 } | 888 } |
| 869 | 889 |
| 870 // All handles closed and all data read. | 890 // All handles closed and all data read. |
| 871 result->set_stdout_data(out_data.GetData()); | 891 result->set_stdout_data(out_data.GetData()); |
| 872 result->set_stderr_data(err_data.GetData()); | 892 result->set_stderr_data(err_data.GetData()); |
| 873 | 893 |
| 874 // Calculate the exit code. | 894 // Calculate the exit code. |
| 875 intptr_t exit_code = exit_code_data.ints[0]; | 895 intptr_t exit_code = exit_code_data.ints[0]; |
| 876 intptr_t negative = exit_code_data.ints[1]; | 896 intptr_t negative = exit_code_data.ints[1]; |
| 877 if (negative) exit_code = -exit_code; | 897 if (negative != 0) { |
| 898 exit_code = -exit_code; |
| 899 } |
| 878 result->set_exit_code(exit_code); | 900 result->set_exit_code(exit_code); |
| 879 | 901 |
| 880 return true; | 902 return true; |
| 881 } | 903 } |
| 882 | 904 |
| 883 | 905 |
| 884 bool Process::Kill(intptr_t id, int signal) { | 906 bool Process::Kill(intptr_t id, int signal) { |
| 885 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); | 907 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); |
| 886 } | 908 } |
| 887 | 909 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 | 951 |
| 930 | 952 |
| 931 intptr_t Process::SetSignalHandler(intptr_t signal) { | 953 intptr_t Process::SetSignalHandler(intptr_t signal) { |
| 932 bool found = false; | 954 bool found = false; |
| 933 for (int i = 0; i < kSignalsCount; i++) { | 955 for (int i = 0; i < kSignalsCount; i++) { |
| 934 if (kSignals[i] == signal) { | 956 if (kSignals[i] == signal) { |
| 935 found = true; | 957 found = true; |
| 936 break; | 958 break; |
| 937 } | 959 } |
| 938 } | 960 } |
| 939 if (!found) return -1; | 961 if (!found) { |
| 962 return -1; |
| 963 } |
| 940 int fds[2]; | 964 int fds[2]; |
| 941 if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) { | 965 if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) { |
| 942 return -1; | 966 return -1; |
| 943 } | 967 } |
| 944 if (!FDUtils::SetNonBlocking(fds[0])) { | 968 if (!FDUtils::SetNonBlocking(fds[0])) { |
| 945 VOID_TEMP_FAILURE_RETRY(close(fds[0])); | 969 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
| 946 VOID_TEMP_FAILURE_RETRY(close(fds[1])); | 970 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
| 947 return -1; | 971 return -1; |
| 948 } | 972 } |
| 949 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 973 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 979 | 1003 |
| 980 void Process::ClearSignalHandler(intptr_t signal) { | 1004 void Process::ClearSignalHandler(intptr_t signal) { |
| 981 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 1005 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
| 982 MutexLocker lock(signal_mutex); | 1006 MutexLocker lock(signal_mutex); |
| 983 SignalInfo* handler = signal_handlers; | 1007 SignalInfo* handler = signal_handlers; |
| 984 bool unlisten = true; | 1008 bool unlisten = true; |
| 985 while (handler != NULL) { | 1009 while (handler != NULL) { |
| 986 bool remove = false; | 1010 bool remove = false; |
| 987 if (handler->signal() == signal) { | 1011 if (handler->signal() == signal) { |
| 988 if (handler->port() == Dart_GetMainPortId()) { | 1012 if (handler->port() == Dart_GetMainPortId()) { |
| 989 if (signal_handlers == handler) signal_handlers = handler->next(); | 1013 if (signal_handlers == handler) { |
| 1014 signal_handlers = handler->next(); |
| 1015 } |
| 990 handler->Unlink(); | 1016 handler->Unlink(); |
| 991 remove = true; | 1017 remove = true; |
| 992 } else { | 1018 } else { |
| 993 unlisten = false; | 1019 unlisten = false; |
| 994 } | 1020 } |
| 995 } | 1021 } |
| 996 SignalInfo* next = handler->next(); | 1022 SignalInfo* next = handler->next(); |
| 997 if (remove) delete handler; | 1023 if (remove) { |
| 1024 delete handler; |
| 1025 } |
| 998 handler = next; | 1026 handler = next; |
| 999 } | 1027 } |
| 1000 if (unlisten) { | 1028 if (unlisten) { |
| 1001 struct sigaction act; | 1029 struct sigaction act; |
| 1002 bzero(&act, sizeof(act)); | 1030 bzero(&act, sizeof(act)); |
| 1003 act.sa_handler = SIG_DFL; | 1031 act.sa_handler = SIG_DFL; |
| 1004 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1032 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
| 1005 } | 1033 } |
| 1006 } | 1034 } |
| 1007 | 1035 |
| 1008 } // namespace bin | 1036 } // namespace bin |
| 1009 } // namespace dart | 1037 } // namespace dart |
| 1010 | 1038 |
| 1011 #endif // defined(TARGET_OS_ANDROID) | 1039 #endif // defined(TARGET_OS_ANDROID) |
| OLD | NEW |