Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(353)

Side by Side Diff: runtime/bin/process_android.cc

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

Powered by Google App Engine
This is Rietveld 408576698