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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
6 | 6 |
7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
8 #if defined(HOST_OS_ANDROID) | 8 #if defined(HOST_OS_ANDROID) |
9 | 9 |
10 #include "bin/process.h" | 10 #include "bin/process.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 void set_next(ProcessInfo* info) { next_ = info; } | 57 void set_next(ProcessInfo* info) { next_ = info; } |
58 | 58 |
59 private: | 59 private: |
60 pid_t pid_; | 60 pid_t pid_; |
61 intptr_t fd_; | 61 intptr_t fd_; |
62 ProcessInfo* next_; | 62 ProcessInfo* next_; |
63 | 63 |
64 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); | 64 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); |
65 }; | 65 }; |
66 | 66 |
67 | |
68 // Singly-linked list of ProcessInfo objects for all active processes | 67 // Singly-linked list of ProcessInfo objects for all active processes |
69 // started from Dart. | 68 // started from Dart. |
70 class ProcessInfoList { | 69 class ProcessInfoList { |
71 public: | 70 public: |
72 static void AddProcess(pid_t pid, intptr_t fd) { | 71 static void AddProcess(pid_t pid, intptr_t fd) { |
73 MutexLocker locker(mutex_); | 72 MutexLocker locker(mutex_); |
74 ProcessInfo* info = new ProcessInfo(pid, fd); | 73 ProcessInfo* info = new ProcessInfo(pid, fd); |
75 info->set_next(active_processes_); | 74 info->set_next(active_processes_); |
76 active_processes_ = info; | 75 active_processes_ = info; |
77 } | 76 } |
78 | 77 |
79 | |
80 static intptr_t LookupProcessExitFd(pid_t pid) { | 78 static intptr_t LookupProcessExitFd(pid_t pid) { |
81 MutexLocker locker(mutex_); | 79 MutexLocker locker(mutex_); |
82 ProcessInfo* current = active_processes_; | 80 ProcessInfo* current = active_processes_; |
83 while (current != NULL) { | 81 while (current != NULL) { |
84 if (current->pid() == pid) { | 82 if (current->pid() == pid) { |
85 return current->fd(); | 83 return current->fd(); |
86 } | 84 } |
87 current = current->next(); | 85 current = current->next(); |
88 } | 86 } |
89 return 0; | 87 return 0; |
90 } | 88 } |
91 | 89 |
92 | |
93 static void RemoveProcess(pid_t pid) { | 90 static void RemoveProcess(pid_t pid) { |
94 MutexLocker locker(mutex_); | 91 MutexLocker locker(mutex_); |
95 ProcessInfo* prev = NULL; | 92 ProcessInfo* prev = NULL; |
96 ProcessInfo* current = active_processes_; | 93 ProcessInfo* current = active_processes_; |
97 while (current != NULL) { | 94 while (current != NULL) { |
98 if (current->pid() == pid) { | 95 if (current->pid() == pid) { |
99 if (prev == NULL) { | 96 if (prev == NULL) { |
100 active_processes_ = current->next(); | 97 active_processes_ = current->next(); |
101 } else { | 98 } else { |
102 prev->set_next(current->next()); | 99 prev->set_next(current->next()); |
(...skipping 11 matching lines...) Expand all Loading... |
114 // started from Dart code. | 111 // started from Dart code. |
115 static ProcessInfo* active_processes_; | 112 static ProcessInfo* active_processes_; |
116 // Mutex protecting all accesses to the linked list of active | 113 // Mutex protecting all accesses to the linked list of active |
117 // processes. | 114 // processes. |
118 static Mutex* mutex_; | 115 static Mutex* mutex_; |
119 | 116 |
120 DISALLOW_ALLOCATION(); | 117 DISALLOW_ALLOCATION(); |
121 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); | 118 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); |
122 }; | 119 }; |
123 | 120 |
124 | |
125 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 121 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
126 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 122 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
127 | 123 |
128 | |
129 // The exit code handler sets up a separate thread which waits for child | 124 // The exit code handler sets up a separate thread which waits for child |
130 // processes to terminate. That separate thread can then get the exit code from | 125 // processes to terminate. That separate thread can then get the exit code from |
131 // processes that have exited and communicate it to Dart through the | 126 // processes that have exited and communicate it to Dart through the |
132 // event loop. | 127 // event loop. |
133 class ExitCodeHandler { | 128 class ExitCodeHandler { |
134 public: | 129 public: |
135 // Notify the ExitCodeHandler that another process exists. | 130 // Notify the ExitCodeHandler that another process exists. |
136 static void ProcessStarted() { | 131 static void ProcessStarted() { |
137 // Multiple isolates could be starting processes at the same | 132 // Multiple isolates could be starting processes at the same |
138 // time. Make sure that only one ExitCodeHandler thread exists. | 133 // time. Make sure that only one ExitCodeHandler thread exists. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 | 230 |
236 static bool terminate_done_; | 231 static bool terminate_done_; |
237 static int process_count_; | 232 static int process_count_; |
238 static bool running_; | 233 static bool running_; |
239 static Monitor* monitor_; | 234 static Monitor* monitor_; |
240 | 235 |
241 DISALLOW_ALLOCATION(); | 236 DISALLOW_ALLOCATION(); |
242 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); | 237 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); |
243 }; | 238 }; |
244 | 239 |
245 | |
246 bool ExitCodeHandler::running_ = false; | 240 bool ExitCodeHandler::running_ = false; |
247 int ExitCodeHandler::process_count_ = 0; | 241 int ExitCodeHandler::process_count_ = 0; |
248 bool ExitCodeHandler::terminate_done_ = false; | 242 bool ExitCodeHandler::terminate_done_ = false; |
249 Monitor* ExitCodeHandler::monitor_ = new Monitor(); | 243 Monitor* ExitCodeHandler::monitor_ = new Monitor(); |
250 | 244 |
251 | |
252 class ProcessStarter { | 245 class ProcessStarter { |
253 public: | 246 public: |
254 ProcessStarter(const char* path, | 247 ProcessStarter(const char* path, |
255 char* arguments[], | 248 char* arguments[], |
256 intptr_t arguments_length, | 249 intptr_t arguments_length, |
257 const char* working_directory, | 250 const char* working_directory, |
258 char* environment[], | 251 char* environment[], |
259 intptr_t environment_length, | 252 intptr_t environment_length, |
260 ProcessStartMode mode, | 253 ProcessStartMode mode, |
261 intptr_t* in, | 254 intptr_t* in, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 if (environment != NULL) { | 287 if (environment != NULL) { |
295 program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate( | 288 program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate( |
296 (environment_length + 1) * sizeof(*program_environment_))); | 289 (environment_length + 1) * sizeof(*program_environment_))); |
297 for (int i = 0; i < environment_length; i++) { | 290 for (int i = 0; i < environment_length; i++) { |
298 program_environment_[i] = environment[i]; | 291 program_environment_[i] = environment[i]; |
299 } | 292 } |
300 program_environment_[environment_length] = NULL; | 293 program_environment_[environment_length] = NULL; |
301 } | 294 } |
302 } | 295 } |
303 | 296 |
304 | |
305 int Start() { | 297 int Start() { |
306 // Create pipes required. | 298 // Create pipes required. |
307 int err = CreatePipes(); | 299 int err = CreatePipes(); |
308 if (err != 0) { | 300 if (err != 0) { |
309 return err; | 301 return err; |
310 } | 302 } |
311 | 303 |
312 // Fork to create the new process. | 304 // Fork to create the new process. |
313 pid_t pid = TEMP_FAILURE_RETRY(fork()); | 305 pid_t pid = TEMP_FAILURE_RETRY(fork()); |
314 if (pid < 0) { | 306 if (pid < 0) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 | 411 |
420 result = TEMP_FAILURE_RETRY(pipe2(write_out_, O_CLOEXEC)); | 412 result = TEMP_FAILURE_RETRY(pipe2(write_out_, O_CLOEXEC)); |
421 if (result < 0) { | 413 if (result < 0) { |
422 return CleanupAndReturnError(); | 414 return CleanupAndReturnError(); |
423 } | 415 } |
424 } | 416 } |
425 | 417 |
426 return 0; | 418 return 0; |
427 } | 419 } |
428 | 420 |
429 | |
430 void NewProcess() { | 421 void NewProcess() { |
431 // Wait for parent process before setting up the child process. | 422 // Wait for parent process before setting up the child process. |
432 char msg; | 423 char msg; |
433 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); | 424 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); |
434 if (bytes_read != sizeof(msg)) { | 425 if (bytes_read != sizeof(msg)) { |
435 perror("Failed receiving notification message"); | 426 perror("Failed receiving notification message"); |
436 exit(1); | 427 exit(1); |
437 } | 428 } |
438 if (mode_ == kNormal) { | 429 if (mode_ == kNormal) { |
439 ExecProcess(); | 430 ExecProcess(); |
440 } else { | 431 } else { |
441 ExecDetachedProcess(); | 432 ExecDetachedProcess(); |
442 } | 433 } |
443 } | 434 } |
444 | 435 |
445 | |
446 void ExecProcess() { | 436 void ExecProcess() { |
447 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { | 437 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
448 ReportChildError(); | 438 ReportChildError(); |
449 } | 439 } |
450 | 440 |
451 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { | 441 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
452 ReportChildError(); | 442 ReportChildError(); |
453 } | 443 } |
454 | 444 |
455 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { | 445 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { |
456 ReportChildError(); | 446 ReportChildError(); |
457 } | 447 } |
458 | 448 |
459 if (working_directory_ != NULL && | 449 if (working_directory_ != NULL && |
460 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { | 450 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { |
461 ReportChildError(); | 451 ReportChildError(); |
462 } | 452 } |
463 | 453 |
464 if (program_environment_ != NULL) { | 454 if (program_environment_ != NULL) { |
465 environ = program_environment_; | 455 environ = program_environment_; |
466 } | 456 } |
467 | 457 |
468 VOID_TEMP_FAILURE_RETRY( | 458 VOID_TEMP_FAILURE_RETRY( |
469 execvp(path_, const_cast<char* const*>(program_arguments_))); | 459 execvp(path_, const_cast<char* const*>(program_arguments_))); |
470 | 460 |
471 ReportChildError(); | 461 ReportChildError(); |
472 } | 462 } |
473 | 463 |
474 | |
475 void ExecDetachedProcess() { | 464 void ExecDetachedProcess() { |
476 if (mode_ == kDetached) { | 465 if (mode_ == kDetached) { |
477 ASSERT(write_out_[0] == -1); | 466 ASSERT(write_out_[0] == -1); |
478 ASSERT(write_out_[1] == -1); | 467 ASSERT(write_out_[1] == -1); |
479 ASSERT(read_err_[0] == -1); | 468 ASSERT(read_err_[0] == -1); |
480 ASSERT(read_err_[1] == -1); | 469 ASSERT(read_err_[1] == -1); |
481 // For a detached process the pipe to connect stdout is only used for | 470 // For a detached process the pipe to connect stdout is only used for |
482 // signaling when to do the first fork. | 471 // signaling when to do the first fork. |
483 VOID_TEMP_FAILURE_RETRY(close(read_in_[0])); | 472 VOID_TEMP_FAILURE_RETRY(close(read_in_[0])); |
484 read_in_[0] = -1; | 473 read_in_[0] = -1; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 // Exit the intermediate process. | 511 // Exit the intermediate process. |
523 exit(0); | 512 exit(0); |
524 } | 513 } |
525 } | 514 } |
526 } else { | 515 } else { |
527 // Exit the intermediate process. | 516 // Exit the intermediate process. |
528 exit(0); | 517 exit(0); |
529 } | 518 } |
530 } | 519 } |
531 | 520 |
532 | |
533 int RegisterProcess(pid_t pid) { | 521 int RegisterProcess(pid_t pid) { |
534 int result; | 522 int result; |
535 int event_fds[2]; | 523 int event_fds[2]; |
536 result = TEMP_FAILURE_RETRY(pipe2(event_fds, O_CLOEXEC)); | 524 result = TEMP_FAILURE_RETRY(pipe2(event_fds, O_CLOEXEC)); |
537 if (result < 0) { | 525 if (result < 0) { |
538 return CleanupAndReturnError(); | 526 return CleanupAndReturnError(); |
539 } | 527 } |
540 | 528 |
541 ProcessInfoList::AddProcess(pid, event_fds[1]); | 529 ProcessInfoList::AddProcess(pid, event_fds[1]); |
542 *exit_event_ = event_fds[0]; | 530 *exit_event_ = event_fds[0]; |
543 FDUtils::SetNonBlocking(event_fds[0]); | 531 FDUtils::SetNonBlocking(event_fds[0]); |
544 return 0; | 532 return 0; |
545 } | 533 } |
546 | 534 |
547 | |
548 int ReadExecResult() { | 535 int ReadExecResult() { |
549 int child_errno; | 536 int child_errno; |
550 int bytes_read = -1; | 537 int bytes_read = -1; |
551 // Read exec result from child. If no data is returned the exec was | 538 // Read exec result from child. If no data is returned the exec was |
552 // successful and the exec call closed the pipe. Otherwise the errno | 539 // successful and the exec call closed the pipe. Otherwise the errno |
553 // is written to the pipe. | 540 // is written to the pipe. |
554 bytes_read = FDUtils::ReadFromBlocking(exec_control_[0], &child_errno, | 541 bytes_read = FDUtils::ReadFromBlocking(exec_control_[0], &child_errno, |
555 sizeof(child_errno)); | 542 sizeof(child_errno)); |
556 if (bytes_read == sizeof(child_errno)) { | 543 if (bytes_read == sizeof(child_errno)) { |
557 ReadChildError(); | 544 ReadChildError(); |
558 return child_errno; | 545 return child_errno; |
559 } else if (bytes_read == -1) { | 546 } else if (bytes_read == -1) { |
560 return errno; | 547 return errno; |
561 } | 548 } |
562 return 0; | 549 return 0; |
563 } | 550 } |
564 | 551 |
565 | |
566 int ReadDetachedExecResult(pid_t* pid) { | 552 int ReadDetachedExecResult(pid_t* pid) { |
567 int child_errno; | 553 int child_errno; |
568 int bytes_read = -1; | 554 int bytes_read = -1; |
569 // Read exec result from child. If only pid data is returned the exec was | 555 // Read exec result from child. If only pid data is returned the exec was |
570 // successful and the exec call closed the pipe. Otherwise the errno | 556 // successful and the exec call closed the pipe. Otherwise the errno |
571 // is written to the pipe as well. | 557 // is written to the pipe as well. |
572 int result[2]; | 558 int result[2]; |
573 bytes_read = | 559 bytes_read = |
574 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result)); | 560 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result)); |
575 if (bytes_read == sizeof(int)) { | 561 if (bytes_read == sizeof(int)) { |
576 *pid = result[0]; | 562 *pid = result[0]; |
577 } else if (bytes_read == 2 * sizeof(int)) { | 563 } else if (bytes_read == 2 * sizeof(int)) { |
578 *pid = result[0]; | 564 *pid = result[0]; |
579 child_errno = result[1]; | 565 child_errno = result[1]; |
580 ReadChildError(); | 566 ReadChildError(); |
581 return child_errno; | 567 return child_errno; |
582 } else if (bytes_read == -1) { | 568 } else if (bytes_read == -1) { |
583 return errno; | 569 return errno; |
584 } | 570 } |
585 return 0; | 571 return 0; |
586 } | 572 } |
587 | 573 |
588 | |
589 void SetupDetached() { | 574 void SetupDetached() { |
590 ASSERT(mode_ == kDetached); | 575 ASSERT(mode_ == kDetached); |
591 | 576 |
592 // Close all open file descriptors except for exec_control_[1]. | 577 // Close all open file descriptors except for exec_control_[1]. |
593 int max_fds = sysconf(_SC_OPEN_MAX); | 578 int max_fds = sysconf(_SC_OPEN_MAX); |
594 if (max_fds == -1) { | 579 if (max_fds == -1) { |
595 max_fds = _POSIX_OPEN_MAX; | 580 max_fds = _POSIX_OPEN_MAX; |
596 } | 581 } |
597 for (int fd = 0; fd < max_fds; fd++) { | 582 for (int fd = 0; fd < max_fds; fd++) { |
598 if (fd != exec_control_[1]) { | 583 if (fd != exec_control_[1]) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 ReportChildError(); | 626 ReportChildError(); |
642 } | 627 } |
643 VOID_TEMP_FAILURE_RETRY(close(read_in_[1])); | 628 VOID_TEMP_FAILURE_RETRY(close(read_in_[1])); |
644 | 629 |
645 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { | 630 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { |
646 ReportChildError(); | 631 ReportChildError(); |
647 } | 632 } |
648 VOID_TEMP_FAILURE_RETRY(close(read_err_[1])); | 633 VOID_TEMP_FAILURE_RETRY(close(read_err_[1])); |
649 } | 634 } |
650 | 635 |
651 | |
652 int CleanupAndReturnError() { | 636 int CleanupAndReturnError() { |
653 int actual_errno = errno; | 637 int actual_errno = errno; |
654 // If CleanupAndReturnError is called without an actual errno make | 638 // If CleanupAndReturnError is called without an actual errno make |
655 // sure to return an error anyway. | 639 // sure to return an error anyway. |
656 if (actual_errno == 0) { | 640 if (actual_errno == 0) { |
657 actual_errno = EPERM; | 641 actual_errno = EPERM; |
658 } | 642 } |
659 SetChildOsErrorMessage(); | 643 SetChildOsErrorMessage(); |
660 CloseAllPipes(); | 644 CloseAllPipes(); |
661 return actual_errno; | 645 return actual_errno; |
662 } | 646 } |
663 | 647 |
664 | |
665 void SetChildOsErrorMessage() { | 648 void SetChildOsErrorMessage() { |
666 const int kBufferSize = 1024; | 649 const int kBufferSize = 1024; |
667 char* error_message = DartUtils::ScopedCString(kBufferSize); | 650 char* error_message = DartUtils::ScopedCString(kBufferSize); |
668 Utils::StrError(errno, error_message, kBufferSize); | 651 Utils::StrError(errno, error_message, kBufferSize); |
669 *os_error_message_ = error_message; | 652 *os_error_message_ = error_message; |
670 } | 653 } |
671 | 654 |
672 | |
673 void ReportChildError() { | 655 void ReportChildError() { |
674 // In the case of failure in the child process write the errno and | 656 // In the case of failure in the child process write the errno and |
675 // the OS error message to the exec control pipe and exit. | 657 // the OS error message to the exec control pipe and exit. |
676 int child_errno = errno; | 658 int child_errno = errno; |
677 const int kBufferSize = 1024; | 659 const int kBufferSize = 1024; |
678 char os_error_message[kBufferSize]; | 660 char os_error_message[kBufferSize]; |
679 Utils::StrError(errno, os_error_message, kBufferSize); | 661 Utils::StrError(errno, os_error_message, kBufferSize); |
680 int bytes_written = FDUtils::WriteToBlocking(exec_control_[1], &child_errno, | 662 int bytes_written = FDUtils::WriteToBlocking(exec_control_[1], &child_errno, |
681 sizeof(child_errno)); | 663 sizeof(child_errno)); |
682 if (bytes_written == sizeof(child_errno)) { | 664 if (bytes_written == sizeof(child_errno)) { |
683 FDUtils::WriteToBlocking(exec_control_[1], os_error_message, | 665 FDUtils::WriteToBlocking(exec_control_[1], os_error_message, |
684 strlen(os_error_message) + 1); | 666 strlen(os_error_message) + 1); |
685 } | 667 } |
686 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); | 668 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); |
687 | 669 |
688 // We avoid running through registered atexit() handlers because that is | 670 // We avoid running through registered atexit() handlers because that is |
689 // unnecessary work. | 671 // unnecessary work. |
690 _exit(1); | 672 _exit(1); |
691 } | 673 } |
692 | 674 |
693 | |
694 void ReportPid(int pid) { | 675 void ReportPid(int pid) { |
695 // In the case of starting a detached process the actual pid of that process | 676 // In the case of starting a detached process the actual pid of that process |
696 // is communicated using the exec control pipe. | 677 // is communicated using the exec control pipe. |
697 int bytes_written = | 678 int bytes_written = |
698 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid)); | 679 FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid)); |
699 ASSERT(bytes_written == sizeof(int)); | 680 ASSERT(bytes_written == sizeof(int)); |
700 USE(bytes_written); | 681 USE(bytes_written); |
701 } | 682 } |
702 | 683 |
703 | |
704 void ReadChildError() { | 684 void ReadChildError() { |
705 const int kMaxMessageSize = 256; | 685 const int kMaxMessageSize = 256; |
706 char* message = DartUtils::ScopedCString(kMaxMessageSize); | 686 char* message = DartUtils::ScopedCString(kMaxMessageSize); |
707 if (message != NULL) { | 687 if (message != NULL) { |
708 FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize); | 688 FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize); |
709 message[kMaxMessageSize - 1] = '\0'; | 689 message[kMaxMessageSize - 1] = '\0'; |
710 *os_error_message_ = message; | 690 *os_error_message_ = message; |
711 } else { | 691 } else { |
712 // Could not get error message. It will be NULL. | 692 // Could not get error message. It will be NULL. |
713 ASSERT(*os_error_message_ == NULL); | 693 ASSERT(*os_error_message_ == NULL); |
714 } | 694 } |
715 } | 695 } |
716 | 696 |
717 | |
718 void ClosePipe(int* fds) { | 697 void ClosePipe(int* fds) { |
719 for (int i = 0; i < 2; i++) { | 698 for (int i = 0; i < 2; i++) { |
720 if (fds[i] != -1) { | 699 if (fds[i] != -1) { |
721 VOID_TEMP_FAILURE_RETRY(close(fds[i])); | 700 VOID_TEMP_FAILURE_RETRY(close(fds[i])); |
722 fds[i] = -1; | 701 fds[i] = -1; |
723 } | 702 } |
724 } | 703 } |
725 } | 704 } |
726 | 705 |
727 | |
728 void CloseAllPipes() { | 706 void CloseAllPipes() { |
729 ClosePipe(exec_control_); | 707 ClosePipe(exec_control_); |
730 ClosePipe(read_in_); | 708 ClosePipe(read_in_); |
731 ClosePipe(read_err_); | 709 ClosePipe(read_err_); |
732 ClosePipe(write_out_); | 710 ClosePipe(write_out_); |
733 } | 711 } |
734 | 712 |
735 | |
736 int read_in_[2]; // Pipe for stdout to child process. | 713 int read_in_[2]; // Pipe for stdout to child process. |
737 int read_err_[2]; // Pipe for stderr to child process. | 714 int read_err_[2]; // Pipe for stderr to child process. |
738 int write_out_[2]; // Pipe for stdin to child process. | 715 int write_out_[2]; // Pipe for stdin to child process. |
739 int exec_control_[2]; // Pipe to get the result from exec. | 716 int exec_control_[2]; // Pipe to get the result from exec. |
740 | 717 |
741 char** program_arguments_; | 718 char** program_arguments_; |
742 char** program_environment_; | 719 char** program_environment_; |
743 | 720 |
744 const char* path_; | 721 const char* path_; |
745 const char* working_directory_; | 722 const char* working_directory_; |
746 ProcessStartMode mode_; | 723 ProcessStartMode mode_; |
747 intptr_t* in_; | 724 intptr_t* in_; |
748 intptr_t* out_; | 725 intptr_t* out_; |
749 intptr_t* err_; | 726 intptr_t* err_; |
750 intptr_t* id_; | 727 intptr_t* id_; |
751 intptr_t* exit_event_; | 728 intptr_t* exit_event_; |
752 char** os_error_message_; | 729 char** os_error_message_; |
753 | 730 |
754 DISALLOW_ALLOCATION(); | 731 DISALLOW_ALLOCATION(); |
755 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); | 732 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); |
756 }; | 733 }; |
757 | 734 |
758 | |
759 int Process::Start(const char* path, | 735 int Process::Start(const char* path, |
760 char* arguments[], | 736 char* arguments[], |
761 intptr_t arguments_length, | 737 intptr_t arguments_length, |
762 const char* working_directory, | 738 const char* working_directory, |
763 char* environment[], | 739 char* environment[], |
764 intptr_t environment_length, | 740 intptr_t environment_length, |
765 ProcessStartMode mode, | 741 ProcessStartMode mode, |
766 intptr_t* in, | 742 intptr_t* in, |
767 intptr_t* out, | 743 intptr_t* out, |
768 intptr_t* err, | 744 intptr_t* err, |
769 intptr_t* id, | 745 intptr_t* id, |
770 intptr_t* exit_event, | 746 intptr_t* exit_event, |
771 char** os_error_message) { | 747 char** os_error_message) { |
772 ProcessStarter starter(path, arguments, arguments_length, working_directory, | 748 ProcessStarter starter(path, arguments, arguments_length, working_directory, |
773 environment, environment_length, mode, in, out, err, | 749 environment, environment_length, mode, in, out, err, |
774 id, exit_event, os_error_message); | 750 id, exit_event, os_error_message); |
775 return starter.Start(); | 751 return starter.Start(); |
776 } | 752 } |
777 | 753 |
778 | |
779 static bool CloseProcessBuffers(struct pollfd fds[3]) { | 754 static bool CloseProcessBuffers(struct pollfd fds[3]) { |
780 int e = errno; | 755 int e = errno; |
781 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); | 756 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); |
782 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); | 757 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); |
783 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); | 758 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); |
784 errno = e; | 759 errno = e; |
785 return false; | 760 return false; |
786 } | 761 } |
787 | 762 |
788 | |
789 bool Process::Wait(intptr_t pid, | 763 bool Process::Wait(intptr_t pid, |
790 intptr_t in, | 764 intptr_t in, |
791 intptr_t out, | 765 intptr_t out, |
792 intptr_t err, | 766 intptr_t err, |
793 intptr_t exit_event, | 767 intptr_t exit_event, |
794 ProcessResult* result) { | 768 ProcessResult* result) { |
795 // Close input to the process right away. | 769 // Close input to the process right away. |
796 VOID_TEMP_FAILURE_RETRY(close(in)); | 770 VOID_TEMP_FAILURE_RETRY(close(in)); |
797 | 771 |
798 // There is no return from this function using Dart_PropagateError | 772 // There is no return from this function using Dart_PropagateError |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 intptr_t exit_code = exit_code_data.ints[0]; | 840 intptr_t exit_code = exit_code_data.ints[0]; |
867 intptr_t negative = exit_code_data.ints[1]; | 841 intptr_t negative = exit_code_data.ints[1]; |
868 if (negative != 0) { | 842 if (negative != 0) { |
869 exit_code = -exit_code; | 843 exit_code = -exit_code; |
870 } | 844 } |
871 result->set_exit_code(exit_code); | 845 result->set_exit_code(exit_code); |
872 | 846 |
873 return true; | 847 return true; |
874 } | 848 } |
875 | 849 |
876 | |
877 bool Process::Kill(intptr_t id, int signal) { | 850 bool Process::Kill(intptr_t id, int signal) { |
878 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); | 851 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); |
879 } | 852 } |
880 | 853 |
881 | |
882 void Process::TerminateExitCodeHandler() { | 854 void Process::TerminateExitCodeHandler() { |
883 ExitCodeHandler::TerminateExitCodeThread(); | 855 ExitCodeHandler::TerminateExitCodeThread(); |
884 } | 856 } |
885 | 857 |
886 | |
887 intptr_t Process::CurrentProcessId() { | 858 intptr_t Process::CurrentProcessId() { |
888 return static_cast<intptr_t>(getpid()); | 859 return static_cast<intptr_t>(getpid()); |
889 } | 860 } |
890 | 861 |
891 | |
892 int64_t Process::CurrentRSS() { | 862 int64_t Process::CurrentRSS() { |
893 // The second value in /proc/self/statm is the current RSS in pages. | 863 // The second value in /proc/self/statm is the current RSS in pages. |
894 File* statm = File::Open("/proc/self/statm", File::kRead); | 864 File* statm = File::Open("/proc/self/statm", File::kRead); |
895 if (statm == NULL) { | 865 if (statm == NULL) { |
896 return -1; | 866 return -1; |
897 } | 867 } |
898 RefCntReleaseScope<File> releaser(statm); | 868 RefCntReleaseScope<File> releaser(statm); |
899 const intptr_t statm_length = 1 * KB; | 869 const intptr_t statm_length = 1 * KB; |
900 void* buffer = reinterpret_cast<void*>(Dart_ScopeAllocate(statm_length)); | 870 void* buffer = reinterpret_cast<void*>(Dart_ScopeAllocate(statm_length)); |
901 const intptr_t statm_read = statm->Read(buffer, statm_length); | 871 const intptr_t statm_read = statm->Read(buffer, statm_length); |
902 if (statm_read <= 0) { | 872 if (statm_read <= 0) { |
903 return -1; | 873 return -1; |
904 } | 874 } |
905 int64_t current_rss_pages = 0; | 875 int64_t current_rss_pages = 0; |
906 int matches = sscanf(reinterpret_cast<char*>(buffer), "%*s%" Pd64 "", | 876 int matches = sscanf(reinterpret_cast<char*>(buffer), "%*s%" Pd64 "", |
907 ¤t_rss_pages); | 877 ¤t_rss_pages); |
908 if (matches != 1) { | 878 if (matches != 1) { |
909 return -1; | 879 return -1; |
910 } | 880 } |
911 return current_rss_pages * getpagesize(); | 881 return current_rss_pages * getpagesize(); |
912 } | 882 } |
913 | 883 |
914 | |
915 int64_t Process::MaxRSS() { | 884 int64_t Process::MaxRSS() { |
916 struct rusage usage; | 885 struct rusage usage; |
917 usage.ru_maxrss = 0; | 886 usage.ru_maxrss = 0; |
918 int r = getrusage(RUSAGE_SELF, &usage); | 887 int r = getrusage(RUSAGE_SELF, &usage); |
919 if (r < 0) { | 888 if (r < 0) { |
920 return -1; | 889 return -1; |
921 } | 890 } |
922 return usage.ru_maxrss * KB; | 891 return usage.ru_maxrss * KB; |
923 } | 892 } |
924 | 893 |
925 | |
926 static Mutex* signal_mutex = new Mutex(); | 894 static Mutex* signal_mutex = new Mutex(); |
927 static SignalInfo* signal_handlers = NULL; | 895 static SignalInfo* signal_handlers = NULL; |
928 static const int kSignalsCount = 7; | 896 static const int kSignalsCount = 7; |
929 static const int kSignals[kSignalsCount] = { | 897 static const int kSignals[kSignalsCount] = { |
930 SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGWINCH, | 898 SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGWINCH, |
931 SIGQUIT // Allow VMService to listen on SIGQUIT. | 899 SIGQUIT // Allow VMService to listen on SIGQUIT. |
932 }; | 900 }; |
933 | 901 |
934 | |
935 SignalInfo::~SignalInfo() { | 902 SignalInfo::~SignalInfo() { |
936 VOID_TEMP_FAILURE_RETRY(close(fd_)); | 903 VOID_TEMP_FAILURE_RETRY(close(fd_)); |
937 } | 904 } |
938 | 905 |
939 | |
940 static void SignalHandler(int signal) { | 906 static void SignalHandler(int signal) { |
941 MutexLocker lock(signal_mutex); | 907 MutexLocker lock(signal_mutex); |
942 const SignalInfo* handler = signal_handlers; | 908 const SignalInfo* handler = signal_handlers; |
943 while (handler != NULL) { | 909 while (handler != NULL) { |
944 if (handler->signal() == signal) { | 910 if (handler->signal() == signal) { |
945 int value = 0; | 911 int value = 0; |
946 VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1)); | 912 VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1)); |
947 } | 913 } |
948 handler = handler->next(); | 914 handler = handler->next(); |
949 } | 915 } |
950 } | 916 } |
951 | 917 |
952 | |
953 intptr_t Process::SetSignalHandler(intptr_t signal) { | 918 intptr_t Process::SetSignalHandler(intptr_t signal) { |
954 bool found = false; | 919 bool found = false; |
955 for (int i = 0; i < kSignalsCount; i++) { | 920 for (int i = 0; i < kSignalsCount; i++) { |
956 if (kSignals[i] == signal) { | 921 if (kSignals[i] == signal) { |
957 found = true; | 922 found = true; |
958 break; | 923 break; |
959 } | 924 } |
960 } | 925 } |
961 if (!found) { | 926 if (!found) { |
962 return -1; | 927 return -1; |
(...skipping 30 matching lines...) Expand all Loading... |
993 if (status < 0) { | 958 if (status < 0) { |
994 VOID_TEMP_FAILURE_RETRY(close(fds[0])); | 959 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
995 VOID_TEMP_FAILURE_RETRY(close(fds[1])); | 960 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
996 return -1; | 961 return -1; |
997 } | 962 } |
998 } | 963 } |
999 signal_handlers = new SignalInfo(fds[1], signal, signal_handlers); | 964 signal_handlers = new SignalInfo(fds[1], signal, signal_handlers); |
1000 return fds[0]; | 965 return fds[0]; |
1001 } | 966 } |
1002 | 967 |
1003 | |
1004 void Process::ClearSignalHandler(intptr_t signal, Dart_Port port) { | 968 void Process::ClearSignalHandler(intptr_t signal, Dart_Port port) { |
1005 // Either the port is illegal or there is no current isolate, but not both. | 969 // Either the port is illegal or there is no current isolate, but not both. |
1006 ASSERT((port != ILLEGAL_PORT) || (Dart_CurrentIsolate() == NULL)); | 970 ASSERT((port != ILLEGAL_PORT) || (Dart_CurrentIsolate() == NULL)); |
1007 ASSERT((port == ILLEGAL_PORT) || (Dart_CurrentIsolate() != NULL)); | 971 ASSERT((port == ILLEGAL_PORT) || (Dart_CurrentIsolate() != NULL)); |
1008 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 972 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
1009 MutexLocker lock(signal_mutex); | 973 MutexLocker lock(signal_mutex); |
1010 SignalInfo* handler = signal_handlers; | 974 SignalInfo* handler = signal_handlers; |
1011 bool unlisten = true; | 975 bool unlisten = true; |
1012 while (handler != NULL) { | 976 while (handler != NULL) { |
1013 bool remove = false; | 977 bool remove = false; |
(...skipping 21 matching lines...) Expand all Loading... |
1035 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 999 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
1036 } | 1000 } |
1037 } | 1001 } |
1038 | 1002 |
1039 } // namespace bin | 1003 } // namespace bin |
1040 } // namespace dart | 1004 } // namespace dart |
1041 | 1005 |
1042 #endif // defined(HOST_OS_ANDROID) | 1006 #endif // defined(HOST_OS_ANDROID) |
1043 | 1007 |
1044 #endif // !defined(DART_IO_DISABLED) | 1008 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |