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/fdutils.h" | 19 #include "bin/fdutils.h" |
20 #include "bin/lockers.h" | 20 #include "bin/lockers.h" |
21 #include "bin/log.h" | 21 #include "bin/log.h" |
22 #include "bin/thread.h" | 22 #include "bin/thread.h" |
23 | 23 |
24 #include "platform/signal_blocker.h" | 24 #include "platform/signal_blocker.h" |
25 | 25 |
26 | 26 |
| 27 extern char **environ; |
| 28 |
| 29 |
27 namespace dart { | 30 namespace dart { |
28 namespace bin { | 31 namespace bin { |
29 | 32 |
30 // 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 |
31 // 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. |
32 // ProcessInfo objects are kept in the static singly-linked | 35 // ProcessInfo objects are kept in the static singly-linked |
33 // ProcessInfoList. | 36 // ProcessInfoList. |
34 class ProcessInfo { | 37 class ProcessInfo { |
35 public: | 38 public: |
36 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } | 39 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 if (!running_) { | 147 if (!running_) { |
145 return; | 148 return; |
146 } | 149 } |
147 | 150 |
148 // Set terminate_done_ to false, so we can use it as a guard for our | 151 // Set terminate_done_ to false, so we can use it as a guard for our |
149 // monitor. | 152 // monitor. |
150 running_ = false; | 153 running_ = false; |
151 | 154 |
152 // Fork to wake up waitpid. | 155 // Fork to wake up waitpid. |
153 if (TEMP_FAILURE_RETRY(fork()) == 0) { | 156 if (TEMP_FAILURE_RETRY(fork()) == 0) { |
154 _exit(0); | 157 exit(0); |
155 } | 158 } |
156 | 159 |
157 monitor_->Notify(); | 160 monitor_->Notify(); |
158 | 161 |
159 while (!terminate_done_) { | 162 while (!terminate_done_) { |
160 monitor_->Wait(Monitor::kNoTimeout); | 163 monitor_->Wait(Monitor::kNoTimeout); |
161 } | 164 } |
162 } | 165 } |
163 | 166 |
164 private: | 167 private: |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 return 0; | 407 return 0; |
405 } | 408 } |
406 | 409 |
407 | 410 |
408 void NewProcess() { | 411 void NewProcess() { |
409 // Wait for parent process before setting up the child process. | 412 // Wait for parent process before setting up the child process. |
410 char msg; | 413 char msg; |
411 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); | 414 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); |
412 if (bytes_read != sizeof(msg)) { | 415 if (bytes_read != sizeof(msg)) { |
413 perror("Failed receiving notification message"); | 416 perror("Failed receiving notification message"); |
414 _exit(1); | 417 exit(1); |
415 } | 418 } |
416 if (mode_ == kNormal) { | 419 if (mode_ == kNormal) { |
417 ExecProcess(); | 420 ExecProcess(); |
418 } else { | 421 } else { |
419 ExecDetachedProcess(); | 422 ExecDetachedProcess(); |
420 } | 423 } |
421 } | 424 } |
422 | 425 |
423 | 426 |
424 void ExecProcess() { | 427 void ExecProcess() { |
425 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { | 428 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
426 ReportChildError(); | 429 ReportChildError(); |
427 } | 430 } |
428 | 431 |
429 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { | 432 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
430 ReportChildError(); | 433 ReportChildError(); |
431 } | 434 } |
432 | 435 |
433 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { | 436 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { |
434 ReportChildError(); | 437 ReportChildError(); |
435 } | 438 } |
436 | 439 |
437 if (working_directory_ != NULL && | 440 if (working_directory_ != NULL && |
438 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 441 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { |
439 ReportChildError(); | 442 ReportChildError(); |
440 } | 443 } |
441 | 444 |
442 if (program_environment_ != NULL) { | 445 if (program_environment_ != NULL) { |
443 VOID_TEMP_FAILURE_RETRY( | 446 environ = program_environment_; |
444 execvpe(path_, const_cast<char* const*>(program_arguments_), | |
445 program_environment_)); | |
446 } else { | |
447 VOID_TEMP_FAILURE_RETRY( | |
448 execvp(path_, const_cast<char* const*>(program_arguments_))); | |
449 } | 447 } |
450 | 448 |
| 449 VOID_TEMP_FAILURE_RETRY( |
| 450 execvp(path_, const_cast<char* const*>(program_arguments_))); |
| 451 |
451 ReportChildError(); | 452 ReportChildError(); |
452 } | 453 } |
453 | 454 |
454 | 455 |
455 void ExecDetachedProcess() { | 456 void ExecDetachedProcess() { |
456 if (mode_ == kDetached) { | 457 if (mode_ == kDetached) { |
457 ASSERT(write_out_[0] == -1); | 458 ASSERT(write_out_[0] == -1); |
458 ASSERT(write_out_[1] == -1); | 459 ASSERT(write_out_[1] == -1); |
459 ASSERT(read_err_[0] == -1); | 460 ASSERT(read_err_[0] == -1); |
460 ASSERT(read_err_[1] == -1); | 461 ASSERT(read_err_[1] == -1); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 493 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { |
493 ReportChildError(); | 494 ReportChildError(); |
494 } | 495 } |
495 | 496 |
496 // Report the final PID and do the exec. | 497 // Report the final PID and do the exec. |
497 ReportPid(getpid()); // getpid cannot fail. | 498 ReportPid(getpid()); // getpid cannot fail. |
498 VOID_TEMP_FAILURE_RETRY( | 499 VOID_TEMP_FAILURE_RETRY( |
499 execvp(path_, const_cast<char* const*>(program_arguments_))); | 500 execvp(path_, const_cast<char* const*>(program_arguments_))); |
500 ReportChildError(); | 501 ReportChildError(); |
501 } else { | 502 } else { |
502 // Exit the intermediate process. | 503 // Exit the intermeiate process. |
503 _exit(0); | 504 exit(0); |
504 } | 505 } |
505 } | 506 } |
506 } else { | 507 } else { |
507 // Exit the intermediate process. | 508 // Exit the intermeiate process. |
508 _exit(0); | 509 exit(0); |
509 } | 510 } |
510 } | 511 } |
511 | 512 |
512 | 513 |
513 int RegisterProcess(pid_t pid) { | 514 int RegisterProcess(pid_t pid) { |
514 int result; | 515 int result; |
515 int event_fds[2]; | 516 int event_fds[2]; |
516 result = TEMP_FAILURE_RETRY(pipe2(event_fds, O_CLOEXEC)); | 517 result = TEMP_FAILURE_RETRY(pipe2(event_fds, O_CLOEXEC)); |
517 if (result < 0) { | 518 if (result < 0) { |
518 return CleanupAndReturnError(); | 519 return CleanupAndReturnError(); |
519 } | 520 } |
520 | 521 |
521 ProcessInfoList::AddProcess(pid, event_fds[1]); | 522 ProcessInfoList::AddProcess(pid, event_fds[1]); |
522 *exit_event_ = event_fds[0]; | 523 *exit_event_ = event_fds[0]; |
523 FDUtils::SetNonBlocking(event_fds[0]); | 524 FDUtils::SetNonBlocking(event_fds[0]); |
524 return 0; | 525 return 0; |
525 } | 526 } |
526 | 527 |
527 | 528 |
528 int ReadExecResult() { | 529 int ReadExecResult() { |
529 int child_errno; | 530 int child_errno; |
530 int bytes_read = -1; | 531 int bytes_read = -1; |
531 // Read exec result from child. If no data is returned the exec was | 532 // Read exec result from child. If no data is returned the exec was |
532 // successful and the exec call closed the pipe. Otherwise the errno | 533 // successful and the exec call closed the pipe. Otherwise the errno |
533 // is written to the pipe. | 534 // is written to the pipe. |
534 bytes_read = | 535 bytes_read = |
535 FDUtils::ReadFromBlocking( | 536 FDUtils::ReadFromBlocking( |
536 exec_control_[0], &child_errno, sizeof(child_errno)); | 537 exec_control_[0], &child_errno, sizeof(child_errno)); |
537 if (bytes_read == sizeof(child_errno)) { | 538 if (bytes_read == sizeof(child_errno)) { |
538 SetOSErrorMessage(child_errno); | 539 ReadChildError(); |
539 return child_errno; | 540 return child_errno; |
540 } else if (bytes_read == -1) { | 541 } else if (bytes_read == -1) { |
541 return errno; | 542 return errno; |
542 } | 543 } |
543 return 0; | 544 return 0; |
544 } | 545 } |
545 | 546 |
546 | 547 |
547 int ReadDetachedExecResult(pid_t *pid) { | 548 int ReadDetachedExecResult(pid_t *pid) { |
548 int child_errno; | 549 int child_errno; |
549 int bytes_read = -1; | 550 int bytes_read = -1; |
550 // Read exec result from child. If only pid data is returned the exec was | 551 // Read exec result from child. If only pid data is returned the exec was |
551 // successful and the exec call closed the pipe. Otherwise the errno | 552 // successful and the exec call closed the pipe. Otherwise the errno |
552 // is written to the pipe as well. | 553 // is written to the pipe as well. |
553 int result[2]; | 554 int result[2]; |
554 bytes_read = | 555 bytes_read = |
555 FDUtils::ReadFromBlocking( | 556 FDUtils::ReadFromBlocking( |
556 exec_control_[0], result, sizeof(result)); | 557 exec_control_[0], result, sizeof(result)); |
557 if (bytes_read == sizeof(int)) { | 558 if (bytes_read == sizeof(int)) { |
558 *pid = result[0]; | 559 *pid = result[0]; |
559 } else if (bytes_read == 2 * sizeof(int)) { | 560 } else if (bytes_read == 2 * sizeof(int)) { |
560 *pid = result[0]; | 561 *pid = result[0]; |
561 child_errno = result[1]; | 562 child_errno = result[1]; |
562 SetOSErrorMessage(child_errno); | 563 ReadChildError(); |
563 return child_errno; | 564 return child_errno; |
564 } else if (bytes_read == -1) { | 565 } else if (bytes_read == -1) { |
565 return errno; | 566 return errno; |
566 } | 567 } |
567 return 0; | 568 return 0; |
568 } | 569 } |
569 | 570 |
570 | 571 |
571 void SetupDetached() { | 572 void SetupDetached() { |
572 ASSERT(mode_ == kDetached); | 573 ASSERT(mode_ == kDetached); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 | 643 |
643 void SetChildOsErrorMessage() { | 644 void SetChildOsErrorMessage() { |
644 const int kBufferSize = 1024; | 645 const int kBufferSize = 1024; |
645 char error_message[kBufferSize]; | 646 char error_message[kBufferSize]; |
646 strerror_r(errno, error_message, kBufferSize); | 647 strerror_r(errno, error_message, kBufferSize); |
647 *os_error_message_ = strdup(error_message); | 648 *os_error_message_ = strdup(error_message); |
648 } | 649 } |
649 | 650 |
650 | 651 |
651 void ReportChildError() { | 652 void ReportChildError() { |
652 // In the case of failure in the child process write the errno to the exec | 653 // In the case of failure in the child process write the errno and |
653 // control pipe and exit. | 654 // the OS error message to the exec control pipe and exit. |
654 int child_errno = errno; | 655 int child_errno = errno; |
655 FDUtils::WriteToBlocking( | 656 const int kBufferSize = 1024; |
656 exec_control_[1], &child_errno, sizeof(child_errno)); | 657 char os_error_message[kBufferSize]; |
657 _exit(1); | 658 strerror_r(errno, os_error_message, kBufferSize); |
| 659 int bytes_written = |
| 660 FDUtils::WriteToBlocking( |
| 661 exec_control_[1], &child_errno, sizeof(child_errno)); |
| 662 if (bytes_written == sizeof(child_errno)) { |
| 663 FDUtils::WriteToBlocking( |
| 664 exec_control_[1], os_error_message, strlen(os_error_message) + 1); |
| 665 } |
| 666 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); |
| 667 exit(1); |
658 } | 668 } |
659 | 669 |
660 | 670 |
661 void ReportPid(int pid) { | 671 void ReportPid(int pid) { |
662 // In the case of starting a detached process the actual pid of that process | 672 // In the case of starting a detached process the actual pid of that process |
663 // is communicated using the exec control pipe. | 673 // is communicated using the exec control pipe. |
664 int bytes_written = | 674 int bytes_written = |
665 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid)); | 675 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid)); |
666 ASSERT(bytes_written == sizeof(int)); | 676 ASSERT(bytes_written == sizeof(int)); |
667 USE(bytes_written); | 677 USE(bytes_written); |
668 } | 678 } |
669 | 679 |
670 | 680 |
671 void SetOSErrorMessage(int child_errno) { | 681 void ReadChildError() { |
672 const int kMaxMessageSize = 256; | 682 const int kMaxMessageSize = 256; |
673 char* message = static_cast<char*>(calloc(kMaxMessageSize, 0)); | 683 char* message = static_cast<char*>(malloc(kMaxMessageSize)); |
674 char* os_error_message = strerror_r( | 684 if (message != NULL) { |
675 child_errno, message, kMaxMessageSize - 1); | 685 FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize); |
676 if (message == os_error_message) { | 686 message[kMaxMessageSize - 1] = '\0'; |
677 *os_error_message_ = message; | 687 *os_error_message_ = message; |
678 } else { | 688 } else { |
679 free(message); | 689 // Could not get error message. It will be NULL. |
680 *os_error_message_ = strdup(os_error_message); | 690 ASSERT(*os_error_message_ == NULL); |
681 } | 691 } |
682 } | 692 } |
683 | 693 |
684 | 694 |
685 void ClosePipe(int* fds) { | 695 void ClosePipe(int* fds) { |
686 for (int i = 0; i < 2; i++) { | 696 for (int i = 0; i < 2; i++) { |
687 if (fds[i] != -1) { | 697 if (fds[i] != -1) { |
688 VOID_TEMP_FAILURE_RETRY(close(fds[i])); | 698 VOID_TEMP_FAILURE_RETRY(close(fds[i])); |
689 fds[i] = -1; | 699 fds[i] = -1; |
690 } | 700 } |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 bzero(&act, sizeof(act)); | 998 bzero(&act, sizeof(act)); |
989 act.sa_handler = SIG_DFL; | 999 act.sa_handler = SIG_DFL; |
990 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1000 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
991 } | 1001 } |
992 } | 1002 } |
993 | 1003 |
994 } // namespace bin | 1004 } // namespace bin |
995 } // namespace dart | 1005 } // namespace dart |
996 | 1006 |
997 #endif // defined(TARGET_OS_ANDROID) | 1007 #endif // defined(TARGET_OS_ANDROID) |
OLD | NEW |