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

Side by Side Diff: runtime/bin/process_macos.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_MACOS) 6 #if defined(TARGET_OS_MACOS)
7 7
8 #include "bin/process.h" 8 #include "bin/process.h"
9 9
10 #include <crt_externs.h> // NOLINT 10 #include <crt_externs.h> // NOLINT
11 #include <errno.h> // NOLINT 11 #include <errno.h> // NOLINT
12 #include <fcntl.h> // NOLINT 12 #include <fcntl.h> // NOLINT
13 #include <poll.h> // NOLINT 13 #include <poll.h> // NOLINT
14 #include <signal.h> // NOLINT 14 #include <signal.h> // NOLINT
15 #include <stdio.h> // NOLINT 15 #include <stdio.h> // NOLINT
16 #include <stdlib.h> // NOLINT 16 #include <stdlib.h> // NOLINT
17 #include <string.h> // NOLINT 17 #include <string.h> // NOLINT
18 #include <unistd.h> // NOLINT 18 #include <unistd.h> // NOLINT
19 19
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 26
27 27
28
29 namespace dart { 28 namespace dart {
30 namespace bin { 29 namespace bin {
31 30
32 // ProcessInfo is used to map a process id to the file descriptor for 31 // ProcessInfo is used to map a process id to the file descriptor for
33 // the pipe used to communicate the exit code of the process to Dart. 32 // the pipe used to communicate the exit code of the process to Dart.
34 // ProcessInfo objects are kept in the static singly-linked 33 // ProcessInfo objects are kept in the static singly-linked
35 // ProcessInfoList. 34 // ProcessInfoList.
36 class ProcessInfo { 35 class ProcessInfo {
37 public: 36 public:
38 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } 37 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 if (!running_) { 145 if (!running_) {
147 return; 146 return;
148 } 147 }
149 148
150 // Set terminate_done_ to false, so we can use it as a guard for our 149 // Set terminate_done_ to false, so we can use it as a guard for our
151 // monitor. 150 // monitor.
152 running_ = false; 151 running_ = false;
153 152
154 // Fork to wake up waitpid. 153 // Fork to wake up waitpid.
155 if (TEMP_FAILURE_RETRY(fork()) == 0) { 154 if (TEMP_FAILURE_RETRY(fork()) == 0) {
156 exit(0); 155 _exit(0);
157 } 156 }
158 157
159 monitor_->Notify(); 158 monitor_->Notify();
160 159
161 while (!terminate_done_) { 160 while (!terminate_done_) {
162 monitor_->Wait(Monitor::kNoTimeout); 161 monitor_->Wait(Monitor::kNoTimeout);
163 } 162 }
164 } 163 }
165 164
166 private: 165 private:
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 return 0; 413 return 0;
415 } 414 }
416 415
417 416
418 void NewProcess() { 417 void NewProcess() {
419 // Wait for parent process before setting up the child process. 418 // Wait for parent process before setting up the child process.
420 char msg; 419 char msg;
421 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); 420 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg));
422 if (bytes_read != sizeof(msg)) { 421 if (bytes_read != sizeof(msg)) {
423 perror("Failed receiving notification message"); 422 perror("Failed receiving notification message");
424 exit(1); 423 _exit(1);
425 } 424 }
426 if (mode_ == kNormal) { 425 if (mode_ == kNormal) {
427 ExecProcess(); 426 ExecProcess();
428 } else { 427 } else {
429 ExecDetachedProcess(); 428 ExecDetachedProcess();
430 } 429 }
431 } 430 }
432 431
433 432
434 void ExecProcess() { 433 void ExecProcess() {
435 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { 434 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
436 ReportChildError(); 435 ReportChildError();
437 } 436 }
438 437
439 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { 438 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
440 ReportChildError(); 439 ReportChildError();
441 } 440 }
442 441
443 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { 442 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
444 ReportChildError(); 443 ReportChildError();
445 } 444 }
446 445
447 if (working_directory_ != NULL && 446 if (working_directory_ != NULL &&
448 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { 447 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
449 ReportChildError(); 448 ReportChildError();
450 } 449 }
451 450
452 if (program_environment_ != NULL) { 451 if (program_environment_ != NULL) {
453 // On MacOS you have to do a bit of magic to get to the 452 VOID_TEMP_FAILURE_RETRY(
454 // environment strings. 453 execvpe(path_, const_cast<char* const*>(program_arguments_),
455 char*** environ = _NSGetEnviron(); 454 program_environment_));
456 *environ = program_environment_; 455 } else {
456 VOID_TEMP_FAILURE_RETRY(
457 execvp(path_, const_cast<char* const*>(program_arguments_)));
457 } 458 }
458 459
459 VOID_TEMP_FAILURE_RETRY(
460 execvp(path_, const_cast<char* const*>(program_arguments_)));
461
462 ReportChildError(); 460 ReportChildError();
463 } 461 }
464 462
465 463
466 void ExecDetachedProcess() { 464 void ExecDetachedProcess() {
467 if (mode_ == kDetached) { 465 if (mode_ == kDetached) {
468 ASSERT(write_out_[0] == -1); 466 ASSERT(write_out_[0] == -1);
469 ASSERT(write_out_[1] == -1); 467 ASSERT(write_out_[1] == -1);
470 ASSERT(read_err_[0] == -1); 468 ASSERT(read_err_[0] == -1);
471 ASSERT(read_err_[1] == -1); 469 ASSERT(read_err_[1] == -1);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { 501 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
504 ReportChildError(); 502 ReportChildError();
505 } 503 }
506 504
507 // Report the final PID and do the exec. 505 // Report the final PID and do the exec.
508 ReportPid(getpid()); // getpid cannot fail. 506 ReportPid(getpid()); // getpid cannot fail.
509 VOID_TEMP_FAILURE_RETRY( 507 VOID_TEMP_FAILURE_RETRY(
510 execvp(path_, const_cast<char* const*>(program_arguments_))); 508 execvp(path_, const_cast<char* const*>(program_arguments_)));
511 ReportChildError(); 509 ReportChildError();
512 } else { 510 } else {
513 // Exit the intermeiate process. 511 // Exit the intermediate process.
514 exit(0); 512 _exit(0);
515 } 513 }
516 } 514 }
517 } else { 515 } else {
518 // Exit the intermeiate process. 516 // Exit the intermediate process.
519 exit(0); 517 _exit(0);
520 } 518 }
521 } 519 }
522 520
523 521
524 int RegisterProcess(pid_t pid) { 522 int RegisterProcess(pid_t pid) {
525 int result; 523 int result;
526 int event_fds[2]; 524 int event_fds[2];
527 result = TEMP_FAILURE_RETRY(pipe(event_fds)); 525 result = TEMP_FAILURE_RETRY(pipe(event_fds));
528 if (result < 0) { 526 if (result < 0) {
529 return CleanupAndReturnError(); 527 return CleanupAndReturnError();
(...skipping 11 matching lines...) Expand all
541 int ReadExecResult() { 539 int ReadExecResult() {
542 int child_errno; 540 int child_errno;
543 int bytes_read = -1; 541 int bytes_read = -1;
544 // Read exec result from child. If no data is returned the exec was 542 // Read exec result from child. If no data is returned the exec was
545 // successful and the exec call closed the pipe. Otherwise the errno 543 // successful and the exec call closed the pipe. Otherwise the errno
546 // is written to the pipe. 544 // is written to the pipe.
547 bytes_read = 545 bytes_read =
548 FDUtils::ReadFromBlocking( 546 FDUtils::ReadFromBlocking(
549 exec_control_[0], &child_errno, sizeof(child_errno)); 547 exec_control_[0], &child_errno, sizeof(child_errno));
550 if (bytes_read == sizeof(child_errno)) { 548 if (bytes_read == sizeof(child_errno)) {
551 ReadChildError(); 549 SetOSErrorMessage(child_errno);
552 return child_errno; 550 return child_errno;
553 } else if (bytes_read == -1) { 551 } else if (bytes_read == -1) {
554 return errno; 552 return errno;
555 } 553 }
556 return 0; 554 return 0;
557 } 555 }
558 556
559 557
560 int ReadDetachedExecResult(pid_t *pid) { 558 int ReadDetachedExecResult(pid_t *pid) {
561 int child_errno; 559 int child_errno;
562 int bytes_read = -1; 560 int bytes_read = -1;
563 // Read exec result from child. If only pid data is returned the exec was 561 // Read exec result from child. If only pid data is returned the exec was
564 // successful and the exec call closed the pipe. Otherwise the errno 562 // successful and the exec call closed the pipe. Otherwise the errno
565 // is written to the pipe as well. 563 // is written to the pipe as well.
566 int result[2]; 564 int result[2];
567 bytes_read = 565 bytes_read =
568 FDUtils::ReadFromBlocking( 566 FDUtils::ReadFromBlocking(
569 exec_control_[0], result, sizeof(result)); 567 exec_control_[0], result, sizeof(result));
570 if (bytes_read == sizeof(int)) { 568 if (bytes_read == sizeof(int)) {
571 *pid = result[0]; 569 *pid = result[0];
572 } else if (bytes_read == 2 * sizeof(int)) { 570 } else if (bytes_read == 2 * sizeof(int)) {
573 *pid = result[0]; 571 *pid = result[0];
574 child_errno = result[1]; 572 child_errno = result[1];
575 ReadChildError(); 573 SetOSErrorMessage(child_errno);
576 return child_errno; 574 return child_errno;
577 } else if (bytes_read == -1) { 575 } else if (bytes_read == -1) {
578 return errno; 576 return errno;
579 } 577 }
580 return 0; 578 return 0;
581 } 579 }
582 580
583 581
584 void SetupDetached() { 582 void SetupDetached() {
585 ASSERT(mode_ == kDetached); 583 ASSERT(mode_ == kDetached);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 653
656 void SetChildOsErrorMessage() { 654 void SetChildOsErrorMessage() {
657 const int kBufferSize = 1024; 655 const int kBufferSize = 1024;
658 char error_message[kBufferSize]; 656 char error_message[kBufferSize];
659 strerror_r(errno, error_message, kBufferSize); 657 strerror_r(errno, error_message, kBufferSize);
660 *os_error_message_ = strdup(error_message); 658 *os_error_message_ = strdup(error_message);
661 } 659 }
662 660
663 661
664 void ReportChildError() { 662 void ReportChildError() {
665 // In the case of failure in the child process write the errno and 663 // In the case of failure in the child process write the errno to the exec
666 // the OS error message to the exec control pipe and exit. 664 // control pipe and exit.
667 int child_errno = errno; 665 int child_errno = errno;
668 const int kBufferSize = 1024; 666 FDUtils::WriteToBlocking(
669 char os_error_message[kBufferSize]; 667 exec_control_[1], &child_errno, sizeof(child_errno));
670 strerror_r(errno, os_error_message, kBufferSize); 668 _exit(1);
671 int bytes_written =
672 FDUtils::WriteToBlocking(
673 exec_control_[1], &child_errno, sizeof(child_errno));
674 if (bytes_written == sizeof(child_errno)) {
675 FDUtils::WriteToBlocking(
676 exec_control_[1], os_error_message, strlen(os_error_message) + 1);
677 }
678 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
679 exit(1);
680 } 669 }
681 670
682 671
683 void ReportPid(int pid) { 672 void ReportPid(int pid) {
684 // In the case of starting a detached process the actual pid of that process 673 // In the case of starting a detached process the actual pid of that process
685 // is communicated using the exec control pipe. 674 // is communicated using the exec control pipe.
686 int bytes_written = 675 int bytes_written =
687 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid)); 676 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid));
688 ASSERT(bytes_written == sizeof(int)); 677 ASSERT(bytes_written == sizeof(int));
689 USE(bytes_written); 678 USE(bytes_written);
690 } 679 }
691 680
692 681
693 void ReadChildError() { 682 void SetOSErrorMessage(int child_errno) {
694 const int kMaxMessageSize = 256; 683 const int kMaxMessageSize = 256;
695 char* message = static_cast<char*>(malloc(kMaxMessageSize)); 684 char* message = static_cast<char*>(calloc(kMaxMessageSize, 0));
696 if (message != NULL) { 685 char* os_error_message = strerror_r(
697 FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize); 686 child_errno, message, kMaxMessageSize - 1);
698 message[kMaxMessageSize - 1] = '\0'; 687 if (message == os_error_message) {
699 *os_error_message_ = message; 688 *os_error_message_ = message;
700 } else { 689 } else {
701 // Could not get error message. It will be NULL. 690 free(message);
702 ASSERT(*os_error_message_ == NULL); 691 *os_error_message_ = strdup(os_error_message);
703 } 692 }
704 } 693 }
705 694
706 695
707 void ClosePipe(int* fds) { 696 void ClosePipe(int* fds) {
708 for (int i = 0; i < 2; i++) { 697 for (int i = 0; i < 2; i++) {
709 if (fds[i] != -1) { 698 if (fds[i] != -1) {
710 VOID_TEMP_FAILURE_RETRY(close(fds[i])); 699 VOID_TEMP_FAILURE_RETRY(close(fds[i]));
711 fds[i] = -1; 700 fds[i] = -1;
712 } 701 }
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
1058 bzero(&act, sizeof(act)); 1047 bzero(&act, sizeof(act));
1059 act.sa_handler = SIG_DFL; 1048 act.sa_handler = SIG_DFL;
1060 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); 1049 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
1061 } 1050 }
1062 } 1051 }
1063 1052
1064 } // namespace bin 1053 } // namespace bin
1065 } // namespace dart 1054 } // namespace dart
1066 1055
1067 #endif // defined(TARGET_OS_MACOS) 1056 #endif // defined(TARGET_OS_MACOS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698