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

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

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

Powered by Google App Engine
This is Rietveld 408576698