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