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

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

Powered by Google App Engine
This is Rietveld 408576698