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_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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) |
OLD | NEW |