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

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

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

Powered by Google App Engine
This is Rietveld 408576698