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(HOST_OS_ANDROID) | 6 #if defined(HOST_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/directory.h" |
20 #include "bin/fdutils.h" | 21 #include "bin/fdutils.h" |
21 #include "bin/file.h" | 22 #include "bin/file.h" |
22 #include "bin/lockers.h" | 23 #include "bin/lockers.h" |
23 #include "bin/log.h" | 24 #include "bin/log.h" |
| 25 #include "bin/namespace.h" |
24 #include "bin/reference_counting.h" | 26 #include "bin/reference_counting.h" |
25 #include "bin/thread.h" | 27 #include "bin/thread.h" |
26 | 28 |
27 #include "platform/signal_blocker.h" | 29 #include "platform/signal_blocker.h" |
28 #include "platform/utils.h" | 30 #include "platform/utils.h" |
29 | 31 |
30 extern char** environ; | 32 extern char** environ; |
31 | 33 |
32 namespace dart { | 34 namespace dart { |
33 namespace bin { | 35 namespace bin { |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); | 237 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); |
236 }; | 238 }; |
237 | 239 |
238 bool ExitCodeHandler::running_ = false; | 240 bool ExitCodeHandler::running_ = false; |
239 int ExitCodeHandler::process_count_ = 0; | 241 int ExitCodeHandler::process_count_ = 0; |
240 bool ExitCodeHandler::terminate_done_ = false; | 242 bool ExitCodeHandler::terminate_done_ = false; |
241 Monitor* ExitCodeHandler::monitor_ = new Monitor(); | 243 Monitor* ExitCodeHandler::monitor_ = new Monitor(); |
242 | 244 |
243 class ProcessStarter { | 245 class ProcessStarter { |
244 public: | 246 public: |
245 ProcessStarter(const char* path, | 247 ProcessStarter(Namespace* namespc, |
| 248 const char* path, |
246 char* arguments[], | 249 char* arguments[], |
247 intptr_t arguments_length, | 250 intptr_t arguments_length, |
248 const char* working_directory, | 251 const char* working_directory, |
249 char* environment[], | 252 char* environment[], |
250 intptr_t environment_length, | 253 intptr_t environment_length, |
251 ProcessStartMode mode, | 254 ProcessStartMode mode, |
252 intptr_t* in, | 255 intptr_t* in, |
253 intptr_t* out, | 256 intptr_t* out, |
254 intptr_t* err, | 257 intptr_t* err, |
255 intptr_t* id, | 258 intptr_t* id, |
256 intptr_t* exit_event, | 259 intptr_t* exit_event, |
257 char** os_error_message) | 260 char** os_error_message) |
258 : path_(path), | 261 : namespc_(namespc), |
| 262 path_(path), |
259 working_directory_(working_directory), | 263 working_directory_(working_directory), |
260 mode_(mode), | 264 mode_(mode), |
261 in_(in), | 265 in_(in), |
262 out_(out), | 266 out_(out), |
263 err_(err), | 267 err_(err), |
264 id_(id), | 268 id_(id), |
265 exit_event_(exit_event), | 269 exit_event_(exit_event), |
266 os_error_message_(os_error_message) { | 270 os_error_message_(os_error_message) { |
267 read_in_[0] = -1; | 271 read_in_[0] = -1; |
268 read_in_[1] = -1; | 272 read_in_[1] = -1; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 perror("Failed receiving notification message"); | 428 perror("Failed receiving notification message"); |
425 exit(1); | 429 exit(1); |
426 } | 430 } |
427 if (mode_ == kNormal) { | 431 if (mode_ == kNormal) { |
428 ExecProcess(); | 432 ExecProcess(); |
429 } else { | 433 } else { |
430 ExecDetachedProcess(); | 434 ExecDetachedProcess(); |
431 } | 435 } |
432 } | 436 } |
433 | 437 |
| 438 const char* ResolvePath() { |
| 439 const char* resolved_path = File::GetCanonicalPath(namespc_, path_); |
| 440 return resolved_path == NULL ? path_ : resolved_path; |
| 441 } |
| 442 |
434 void ExecProcess() { | 443 void ExecProcess() { |
435 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { | 444 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
436 ReportChildError(); | 445 ReportChildError(); |
437 } | 446 } |
438 | 447 |
439 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { | 448 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
440 ReportChildError(); | 449 ReportChildError(); |
441 } | 450 } |
442 | 451 |
443 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { | 452 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { |
444 ReportChildError(); | 453 ReportChildError(); |
445 } | 454 } |
446 | 455 |
447 if (working_directory_ != NULL && | 456 if (working_directory_ != NULL && |
448 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 457 !Directory::SetCurrent(namespc_, working_directory_)) { |
449 ReportChildError(); | 458 ReportChildError(); |
450 } | 459 } |
451 | 460 |
452 if (program_environment_ != NULL) { | 461 if (program_environment_ != NULL) { |
453 environ = program_environment_; | 462 environ = program_environment_; |
454 } | 463 } |
455 | 464 |
| 465 const char* resolved_path = ResolvePath(); |
456 VOID_TEMP_FAILURE_RETRY( | 466 VOID_TEMP_FAILURE_RETRY( |
457 execvp(path_, const_cast<char* const*>(program_arguments_))); | 467 execvp(resolved_path, const_cast<char* const*>(program_arguments_))); |
458 | 468 |
459 ReportChildError(); | 469 ReportChildError(); |
460 } | 470 } |
461 | 471 |
462 void ExecDetachedProcess() { | 472 void ExecDetachedProcess() { |
463 if (mode_ == kDetached) { | 473 if (mode_ == kDetached) { |
464 ASSERT(write_out_[0] == -1); | 474 ASSERT(write_out_[0] == -1); |
465 ASSERT(write_out_[1] == -1); | 475 ASSERT(write_out_[1] == -1); |
466 ASSERT(read_err_[0] == -1); | 476 ASSERT(read_err_[0] == -1); |
467 ASSERT(read_err_[1] == -1); | 477 ASSERT(read_err_[1] == -1); |
(...skipping 21 matching lines...) Expand all Loading... |
489 if (pid < 0) { | 499 if (pid < 0) { |
490 ReportChildError(); | 500 ReportChildError(); |
491 } else if (pid == 0) { | 501 } else if (pid == 0) { |
492 if (mode_ == kDetached) { | 502 if (mode_ == kDetached) { |
493 SetupDetached(); | 503 SetupDetached(); |
494 } else { | 504 } else { |
495 SetupDetachedWithStdio(); | 505 SetupDetachedWithStdio(); |
496 } | 506 } |
497 | 507 |
498 if ((working_directory_ != NULL) && | 508 if ((working_directory_ != NULL) && |
499 (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) { | 509 !Directory::SetCurrent(namespc_, working_directory_)) { |
500 ReportChildError(); | 510 ReportChildError(); |
501 } | 511 } |
502 | 512 |
503 // Report the final PID and do the exec. | 513 // Report the final PID and do the exec. |
504 ReportPid(getpid()); // getpid cannot fail. | 514 ReportPid(getpid()); // getpid cannot fail. |
505 VOID_TEMP_FAILURE_RETRY( | 515 const char* resolved_path = ResolvePath(); |
506 execvp(path_, const_cast<char* const*>(program_arguments_))); | 516 VOID_TEMP_FAILURE_RETRY(execvp( |
| 517 resolved_path, const_cast<char* const*>(program_arguments_))); |
507 ReportChildError(); | 518 ReportChildError(); |
508 } else { | 519 } else { |
509 // Exit the intermediate process. | 520 // Exit the intermediate process. |
510 exit(0); | 521 exit(0); |
511 } | 522 } |
512 } | 523 } |
513 } else { | 524 } else { |
514 // Exit the intermediate process. | 525 // Exit the intermediate process. |
515 exit(0); | 526 exit(0); |
516 } | 527 } |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 char* error_message = DartUtils::ScopedCString(kBufferSize); | 659 char* error_message = DartUtils::ScopedCString(kBufferSize); |
649 Utils::StrError(errno, error_message, kBufferSize); | 660 Utils::StrError(errno, error_message, kBufferSize); |
650 *os_error_message_ = error_message; | 661 *os_error_message_ = error_message; |
651 } | 662 } |
652 | 663 |
653 void ReportChildError() { | 664 void ReportChildError() { |
654 // In the case of failure in the child process write the errno and | 665 // In the case of failure in the child process write the errno and |
655 // the OS error message to the exec control pipe and exit. | 666 // the OS error message to the exec control pipe and exit. |
656 int child_errno = errno; | 667 int child_errno = errno; |
657 const int kBufferSize = 1024; | 668 const int kBufferSize = 1024; |
658 char os_error_message[kBufferSize]; | 669 char error_buf[kBufferSize]; |
659 Utils::StrError(errno, os_error_message, kBufferSize); | 670 char* os_error_message = Utils::StrError(errno, error_buf, kBufferSize); |
660 int bytes_written = FDUtils::WriteToBlocking(exec_control_[1], &child_errno, | 671 int bytes_written = FDUtils::WriteToBlocking(exec_control_[1], &child_errno, |
661 sizeof(child_errno)); | 672 sizeof(child_errno)); |
662 if (bytes_written == sizeof(child_errno)) { | 673 if (bytes_written == sizeof(child_errno)) { |
663 FDUtils::WriteToBlocking(exec_control_[1], os_error_message, | 674 FDUtils::WriteToBlocking(exec_control_[1], os_error_message, |
664 strlen(os_error_message) + 1); | 675 strlen(os_error_message) + 1); |
665 } | 676 } |
666 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); | 677 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); |
667 | 678 |
668 // We avoid running through registered atexit() handlers because that is | 679 // We avoid running through registered atexit() handlers because that is |
669 // unnecessary work. | 680 // unnecessary work. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 } | 720 } |
710 | 721 |
711 int read_in_[2]; // Pipe for stdout to child process. | 722 int read_in_[2]; // Pipe for stdout to child process. |
712 int read_err_[2]; // Pipe for stderr to child process. | 723 int read_err_[2]; // Pipe for stderr to child process. |
713 int write_out_[2]; // Pipe for stdin to child process. | 724 int write_out_[2]; // Pipe for stdin to child process. |
714 int exec_control_[2]; // Pipe to get the result from exec. | 725 int exec_control_[2]; // Pipe to get the result from exec. |
715 | 726 |
716 char** program_arguments_; | 727 char** program_arguments_; |
717 char** program_environment_; | 728 char** program_environment_; |
718 | 729 |
| 730 Namespace* namespc_; |
719 const char* path_; | 731 const char* path_; |
720 const char* working_directory_; | 732 const char* working_directory_; |
721 ProcessStartMode mode_; | 733 ProcessStartMode mode_; |
722 intptr_t* in_; | 734 intptr_t* in_; |
723 intptr_t* out_; | 735 intptr_t* out_; |
724 intptr_t* err_; | 736 intptr_t* err_; |
725 intptr_t* id_; | 737 intptr_t* id_; |
726 intptr_t* exit_event_; | 738 intptr_t* exit_event_; |
727 char** os_error_message_; | 739 char** os_error_message_; |
728 | 740 |
729 DISALLOW_ALLOCATION(); | 741 DISALLOW_ALLOCATION(); |
730 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); | 742 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); |
731 }; | 743 }; |
732 | 744 |
733 int Process::Start(const char* path, | 745 int Process::Start(Namespace* namespc, |
| 746 const char* path, |
734 char* arguments[], | 747 char* arguments[], |
735 intptr_t arguments_length, | 748 intptr_t arguments_length, |
736 const char* working_directory, | 749 const char* working_directory, |
737 char* environment[], | 750 char* environment[], |
738 intptr_t environment_length, | 751 intptr_t environment_length, |
739 ProcessStartMode mode, | 752 ProcessStartMode mode, |
740 intptr_t* in, | 753 intptr_t* in, |
741 intptr_t* out, | 754 intptr_t* out, |
742 intptr_t* err, | 755 intptr_t* err, |
743 intptr_t* id, | 756 intptr_t* id, |
744 intptr_t* exit_event, | 757 intptr_t* exit_event, |
745 char** os_error_message) { | 758 char** os_error_message) { |
746 ProcessStarter starter(path, arguments, arguments_length, working_directory, | 759 ProcessStarter starter(namespc, path, arguments, arguments_length, |
747 environment, environment_length, mode, in, out, err, | 760 working_directory, environment, environment_length, |
748 id, exit_event, os_error_message); | 761 mode, in, out, err, id, exit_event, os_error_message); |
749 return starter.Start(); | 762 return starter.Start(); |
750 } | 763 } |
751 | 764 |
752 static bool CloseProcessBuffers(struct pollfd fds[3]) { | 765 static bool CloseProcessBuffers(struct pollfd fds[3]) { |
753 int e = errno; | 766 int e = errno; |
754 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); | 767 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); |
755 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); | 768 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); |
756 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); | 769 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); |
757 errno = e; | 770 errno = e; |
758 return false; | 771 return false; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 bzero(&act, sizeof(act)); | 1010 bzero(&act, sizeof(act)); |
998 act.sa_handler = SIG_DFL; | 1011 act.sa_handler = SIG_DFL; |
999 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1012 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
1000 } | 1013 } |
1001 } | 1014 } |
1002 | 1015 |
1003 } // namespace bin | 1016 } // namespace bin |
1004 } // namespace dart | 1017 } // namespace dart |
1005 | 1018 |
1006 #endif // defined(HOST_OS_ANDROID) | 1019 #endif // defined(HOST_OS_ANDROID) |
OLD | NEW |