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

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

Issue 1800863002: Cleanup in //runtime/bin (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Windows fixes Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_LINUX) 6 #if defined(TARGET_OS_LINUX)
7 7
8 #include "bin/process.h" 8 #include "bin/process.h"
9 9
10 #include <errno.h> // NOLINT 10 #include <errno.h> // NOLINT
11 #include <fcntl.h> // NOLINT 11 #include <fcntl.h> // NOLINT
12 #include <poll.h> // NOLINT 12 #include <poll.h> // NOLINT
13 #include <stdio.h> // NOLINT 13 #include <stdio.h> // NOLINT
14 #include <stdlib.h> // NOLINT 14 #include <stdlib.h> // NOLINT
15 #include <string.h> // NOLINT 15 #include <string.h> // NOLINT
16 #include <sys/wait.h> // NOLINT 16 #include <sys/wait.h> // NOLINT
17 #include <unistd.h> // NOLINT 17 #include <unistd.h> // NOLINT
18 18
19 #include "bin/dartutils.h" 19 #include "bin/dartutils.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 #include "platform/signal_blocker.h" 24 #include "platform/signal_blocker.h"
25 #include "platform/utils.h" 25 #include "platform/utils.h"
26 26
27
28 extern char **environ; 27 extern char **environ;
29 28
30
31 namespace dart { 29 namespace dart {
32 namespace bin { 30 namespace bin {
33 31
34 // 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
35 // 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.
36 // ProcessInfo objects are kept in the static singly-linked 34 // ProcessInfo objects are kept in the static singly-linked
37 // ProcessInfoList. 35 // ProcessInfoList.
38 class ProcessInfo { 36 class ProcessInfo {
39 public: 37 public:
40 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } 38 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { }
41 ~ProcessInfo() { 39 ~ProcessInfo() {
42 int closed = TEMP_FAILURE_RETRY(close(fd_)); 40 int closed = TEMP_FAILURE_RETRY(close(fd_));
43 if (closed != 0) { 41 if (closed != 0) {
44 FATAL("Failed to close process exit code pipe"); 42 FATAL("Failed to close process exit code pipe");
45 } 43 }
46 } 44 }
47 pid_t pid() { return pid_; } 45 pid_t pid() { return pid_; }
48 intptr_t fd() { return fd_; } 46 intptr_t fd() { return fd_; }
49 ProcessInfo* next() { return next_; } 47 ProcessInfo* next() { return next_; }
50 void set_next(ProcessInfo* info) { next_ = info; } 48 void set_next(ProcessInfo* info) { next_ = info; }
51 49
52 private: 50 private:
53 pid_t pid_; 51 pid_t pid_;
54 intptr_t fd_; 52 intptr_t fd_;
55 ProcessInfo* next_; 53 ProcessInfo* next_;
54
55 DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
56 }; 56 };
57 57
58 58
59 // Singly-linked list of ProcessInfo objects for all active processes 59 // Singly-linked list of ProcessInfo objects for all active processes
60 // started from Dart. 60 // started from Dart.
61 class ProcessInfoList { 61 class ProcessInfoList {
62 public: 62 public:
63 static void AddProcess(pid_t pid, intptr_t fd) { 63 static void AddProcess(pid_t pid, intptr_t fd) {
64 MutexLocker locker(mutex_); 64 MutexLocker locker(mutex_);
65 ProcessInfo* info = new ProcessInfo(pid, fd); 65 ProcessInfo* info = new ProcessInfo(pid, fd);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } 100 }
101 } 101 }
102 102
103 private: 103 private:
104 // Linked list of ProcessInfo objects for all active processes 104 // Linked list of ProcessInfo objects for all active processes
105 // started from Dart code. 105 // started from Dart code.
106 static ProcessInfo* active_processes_; 106 static ProcessInfo* active_processes_;
107 // Mutex protecting all accesses to the linked list of active 107 // Mutex protecting all accesses to the linked list of active
108 // processes. 108 // processes.
109 static Mutex* mutex_; 109 static Mutex* mutex_;
110
111 DISALLOW_ALLOCATION();
112 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
110 }; 113 };
111 114
112 115
113 ProcessInfo* ProcessInfoList::active_processes_ = NULL; 116 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
114 Mutex* ProcessInfoList::mutex_ = new Mutex(); 117 Mutex* ProcessInfoList::mutex_ = new Mutex();
115 118
116 119
117 // The exit code handler sets up a separate thread which waits for child 120 // The exit code handler sets up a separate thread which waits for child
118 // processes to terminate. That separate thread can then get the exit code from 121 // processes to terminate. That separate thread can then get the exit code from
119 // processes that have exited and communicate it to Dart through the 122 // processes that have exited and communicate it to Dart through the
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 } 199 }
197 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); 200 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid);
198 if (exit_code_fd != 0) { 201 if (exit_code_fd != 0) {
199 int message[2] = { exit_code, negative }; 202 int message[2] = { exit_code, negative };
200 ssize_t result = 203 ssize_t result =
201 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); 204 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message));
202 // If the process has been closed, the read end of the exit 205 // If the process has been closed, the read end of the exit
203 // pipe has been closed. It is therefore not a problem that 206 // pipe has been closed. It is therefore not a problem that
204 // write fails with a broken pipe error. Other errors should 207 // write fails with a broken pipe error. Other errors should
205 // not happen. 208 // not happen.
206 if (result != -1 && result != sizeof(message)) { 209 if ((result != -1) && (result != sizeof(message))) {
207 FATAL("Failed to write entire process exit message"); 210 FATAL("Failed to write entire process exit message");
208 } else if (result == -1 && errno != EPIPE) { 211 } else if ((result == -1) && (errno != EPIPE)) {
209 FATAL1("Failed to write exit code: %d", errno); 212 FATAL1("Failed to write exit code: %d", errno);
210 } 213 }
211 ProcessInfoList::RemoveProcess(pid); 214 ProcessInfoList::RemoveProcess(pid);
212 { 215 {
213 MonitorLocker locker(monitor_); 216 MonitorLocker locker(monitor_);
214 process_count_--; 217 process_count_--;
215 } 218 }
216 } 219 }
217 } 220 }
218 } 221 }
219 } 222 }
220 223
221 static bool terminate_done_; 224 static bool terminate_done_;
222 static int process_count_; 225 static int process_count_;
223 static bool running_; 226 static bool running_;
224 static Monitor* monitor_; 227 static Monitor* monitor_;
228
229 DISALLOW_ALLOCATION();
230 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
225 }; 231 };
226 232
227 233
228 bool ExitCodeHandler::running_ = false; 234 bool ExitCodeHandler::running_ = false;
229 int ExitCodeHandler::process_count_ = 0; 235 int ExitCodeHandler::process_count_ = 0;
230 bool ExitCodeHandler::terminate_done_ = false; 236 bool ExitCodeHandler::terminate_done_ = false;
231 Monitor* ExitCodeHandler::monitor_ = new Monitor(); 237 Monitor* ExitCodeHandler::monitor_ = new Monitor();
232 238
233 239
234 class ProcessStarter { 240 class ProcessStarter {
(...skipping 22 matching lines...) Expand all
257 os_error_message_(os_error_message) { 263 os_error_message_(os_error_message) {
258 read_in_[0] = -1; 264 read_in_[0] = -1;
259 read_in_[1] = -1; 265 read_in_[1] = -1;
260 read_err_[0] = -1; 266 read_err_[0] = -1;
261 read_err_[1] = -1; 267 read_err_[1] = -1;
262 write_out_[0] = -1; 268 write_out_[0] = -1;
263 write_out_[1] = -1; 269 write_out_[1] = -1;
264 exec_control_[0] = -1; 270 exec_control_[0] = -1;
265 exec_control_[1] = -1; 271 exec_control_[1] = -1;
266 272
267 program_arguments_ = new char*[arguments_length + 2]; 273 program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
zra 2016/03/15 18:12:29 Changed to scope allocate.
274 (arguments_length + 2) * sizeof(*program_arguments_)));
268 program_arguments_[0] = const_cast<char*>(path_); 275 program_arguments_[0] = const_cast<char*>(path_);
269 for (int i = 0; i < arguments_length; i++) { 276 for (int i = 0; i < arguments_length; i++) {
270 program_arguments_[i + 1] = arguments[i]; 277 program_arguments_[i + 1] = arguments[i];
271 } 278 }
272 program_arguments_[arguments_length + 1] = NULL; 279 program_arguments_[arguments_length + 1] = NULL;
273 280
274 program_environment_ = NULL; 281 program_environment_ = NULL;
275 if (environment != NULL) { 282 if (environment != NULL) {
276 program_environment_ = new char*[environment_length + 1]; 283 program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
zra 2016/03/15 18:12:29 ditto.
284 (environment_length + 1) * sizeof(*program_environment_)));
277 for (int i = 0; i < environment_length; i++) { 285 for (int i = 0; i < environment_length; i++) {
278 program_environment_[i] = environment[i]; 286 program_environment_[i] = environment[i];
279 } 287 }
280 program_environment_[environment_length] = NULL; 288 program_environment_[environment_length] = NULL;
281 } 289 }
282 } 290 }
283 291
284 292
285 ~ProcessStarter() {
286 delete[] program_arguments_;
287 delete[] program_environment_;
288 }
289
290
291 int Start() { 293 int Start() {
292 // Create pipes required. 294 // Create pipes required.
293 int err = CreatePipes(); 295 int err = CreatePipes();
294 if (err != 0) return err; 296 if (err != 0) {
297 return err;
298 }
295 299
296 // Fork to create the new process. 300 // Fork to create the new process.
297 pid_t pid = TEMP_FAILURE_RETRY(fork()); 301 pid_t pid = TEMP_FAILURE_RETRY(fork());
298 if (pid < 0) { 302 if (pid < 0) {
299 // Failed to fork. 303 // Failed to fork.
300 return CleanupAndReturnError(); 304 return CleanupAndReturnError();
301 } else if (pid == 0) { 305 } else if (pid == 0) {
302 // This runs in the new process. 306 // This runs in the new process.
303 NewProcess(); 307 NewProcess();
304 } 308 }
305 309
306 // This runs in the original process. 310 // This runs in the original process.
307 311
308 // Be sure to listen for exit-codes, now we have a child-process. 312 // Be sure to listen for exit-codes, now we have a child-process.
309 ExitCodeHandler::ProcessStarted(); 313 ExitCodeHandler::ProcessStarted();
310 314
311 // Register the child process if not detached. 315 // Register the child process if not detached.
312 if (mode_ == kNormal) { 316 if (mode_ == kNormal) {
313 err = RegisterProcess(pid); 317 err = RegisterProcess(pid);
314 if (err != 0) return err; 318 if (err != 0) {
319 return err;
320 }
315 } 321 }
316 322
317 // Notify child process to start. This is done to delay the call to exec 323 // Notify child process to start. This is done to delay the call to exec
318 // until the process is registered above, and we are ready to receive the 324 // until the process is registered above, and we are ready to receive the
319 // exit code. 325 // exit code.
320 char msg = '1'; 326 char msg = '1';
321 int bytes_written = 327 int bytes_written =
322 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg)); 328 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg));
323 if (bytes_written != sizeof(msg)) { 329 if (bytes_written != sizeof(msg)) {
324 return CleanupAndReturnError(); 330 return CleanupAndReturnError();
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 pid = TEMP_FAILURE_RETRY(fork()); 489 pid = TEMP_FAILURE_RETRY(fork());
484 if (pid < 0) { 490 if (pid < 0) {
485 ReportChildError(); 491 ReportChildError();
486 } else if (pid == 0) { 492 } else if (pid == 0) {
487 if (mode_ == kDetached) { 493 if (mode_ == kDetached) {
488 SetupDetached(); 494 SetupDetached();
489 } else { 495 } else {
490 SetupDetachedWithStdio(); 496 SetupDetachedWithStdio();
491 } 497 }
492 498
493 if (working_directory_ != NULL && 499 if ((working_directory_ != NULL) &&
494 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { 500 (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) {
495 ReportChildError(); 501 ReportChildError();
496 } 502 }
497 503
498 // Report the final PID and do the exec. 504 // Report the final PID and do the exec.
499 ReportPid(getpid()); // getpid cannot fail. 505 ReportPid(getpid()); // getpid cannot fail.
500 VOID_TEMP_FAILURE_RETRY( 506 VOID_TEMP_FAILURE_RETRY(
501 execvp(path_, const_cast<char* const*>(program_arguments_))); 507 execvp(path_, const_cast<char* const*>(program_arguments_)));
502 ReportChildError(); 508 ReportChildError();
503 } else { 509 } else {
504 // Exit the intermeiate process. 510 // Exit the intermeiate process.
(...skipping 21 matching lines...) Expand all
526 return 0; 532 return 0;
527 } 533 }
528 534
529 535
530 int ReadExecResult() { 536 int ReadExecResult() {
531 int child_errno; 537 int child_errno;
532 int bytes_read = -1; 538 int bytes_read = -1;
533 // 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
534 // successful and the exec call closed the pipe. Otherwise the errno 540 // successful and the exec call closed the pipe. Otherwise the errno
535 // is written to the pipe. 541 // is written to the pipe.
536 bytes_read = 542 bytes_read = FDUtils::ReadFromBlocking(
537 FDUtils::ReadFromBlocking( 543 exec_control_[0], &child_errno, sizeof(child_errno));
538 exec_control_[0], &child_errno, sizeof(child_errno));
539 if (bytes_read == sizeof(child_errno)) { 544 if (bytes_read == sizeof(child_errno)) {
540 ReadChildError(); 545 ReadChildError();
541 return child_errno; 546 return child_errno;
542 } else if (bytes_read == -1) { 547 } else if (bytes_read == -1) {
543 return errno; 548 return errno;
544 } 549 }
545 return 0; 550 return 0;
546 } 551 }
547 552
548 553
549 int ReadDetachedExecResult(pid_t *pid) { 554 int ReadDetachedExecResult(pid_t *pid) {
550 int child_errno; 555 int child_errno;
551 int bytes_read = -1; 556 int bytes_read = -1;
552 // Read exec result from child. If only pid data is returned the exec was 557 // Read exec result from child. If only pid data is returned the exec was
553 // successful and the exec call closed the pipe. Otherwise the errno 558 // successful and the exec call closed the pipe. Otherwise the errno
554 // is written to the pipe as well. 559 // is written to the pipe as well.
555 int result[2]; 560 int result[2];
556 bytes_read = 561 bytes_read =
557 FDUtils::ReadFromBlocking( 562 FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result));
558 exec_control_[0], result, sizeof(result));
559 if (bytes_read == sizeof(int)) { 563 if (bytes_read == sizeof(int)) {
560 *pid = result[0]; 564 *pid = result[0];
561 } else if (bytes_read == 2 * sizeof(int)) { 565 } else if (bytes_read == 2 * sizeof(int)) {
562 *pid = result[0]; 566 *pid = result[0];
563 child_errno = result[1]; 567 child_errno = result[1];
564 ReadChildError(); 568 ReadChildError();
565 return child_errno; 569 return child_errno;
566 } else if (bytes_read == -1) { 570 } else if (bytes_read == -1) {
567 return errno; 571 return errno;
568 } 572 }
569 return 0; 573 return 0;
570 } 574 }
571 575
572 576
573 void SetupDetached() { 577 void SetupDetached() {
574 ASSERT(mode_ == kDetached); 578 ASSERT(mode_ == kDetached);
575 579
576 // Close all open file descriptors except for exec_control_[1]. 580 // Close all open file descriptors except for exec_control_[1].
577 int max_fds = sysconf(_SC_OPEN_MAX); 581 int max_fds = sysconf(_SC_OPEN_MAX);
578 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; 582 if (max_fds == -1) {
583 max_fds = _POSIX_OPEN_MAX;
584 }
579 for (int fd = 0; fd < max_fds; fd++) { 585 for (int fd = 0; fd < max_fds; fd++) {
580 if (fd != exec_control_[1]) { 586 if (fd != exec_control_[1]) {
581 VOID_TEMP_FAILURE_RETRY(close(fd)); 587 VOID_TEMP_FAILURE_RETRY(close(fd));
582 } 588 }
583 } 589 }
584 590
585 // Re-open stdin, stdout and stderr and connect them to /dev/null. 591 // Re-open stdin, stdout and stderr and connect them to /dev/null.
586 // The loop above should already have closed all of them, so 592 // The loop above should already have closed all of them, so
587 // creating new file descriptors should start at STDIN_FILENO. 593 // creating new file descriptors should start at STDIN_FILENO.
588 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); 594 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
589 if (fd != STDIN_FILENO) { 595 if (fd != STDIN_FILENO) {
590 ReportChildError(); 596 ReportChildError();
591 } 597 }
592 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != 598 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
593 STDOUT_FILENO) { 599 STDOUT_FILENO) {
594 ReportChildError(); 600 ReportChildError();
595 } 601 }
596 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != 602 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
597 STDERR_FILENO) { 603 STDERR_FILENO) {
598 ReportChildError(); 604 ReportChildError();
599 } 605 }
600 } 606 }
601 607
602 void SetupDetachedWithStdio() { 608 void SetupDetachedWithStdio() {
603 // Close all open file descriptors except for 609 // Close all open file descriptors except for
604 // exec_control_[1], write_out_[0], read_in_[1] and 610 // exec_control_[1], write_out_[0], read_in_[1] and
605 // read_err_[1]. 611 // read_err_[1].
606 int max_fds = sysconf(_SC_OPEN_MAX); 612 int max_fds = sysconf(_SC_OPEN_MAX);
607 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; 613 if (max_fds == -1) {
614 max_fds = _POSIX_OPEN_MAX;
615 }
608 for (int fd = 0; fd < max_fds; fd++) { 616 for (int fd = 0; fd < max_fds; fd++) {
609 if (fd != exec_control_[1] && 617 if ((fd != exec_control_[1]) &&
610 fd != write_out_[0] && 618 (fd != write_out_[0]) &&
611 fd != read_in_[1] && 619 (fd != read_in_[1]) &&
612 fd != read_err_[1]) { 620 (fd != read_err_[1])) {
613 VOID_TEMP_FAILURE_RETRY(close(fd)); 621 VOID_TEMP_FAILURE_RETRY(close(fd));
614 } 622 }
615 } 623 }
616 624
617 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { 625 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
618 ReportChildError(); 626 ReportChildError();
619 } 627 }
620 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); 628 VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
621 629
622 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { 630 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
(...skipping 29 matching lines...) Expand all
652 } 660 }
653 661
654 662
655 void ReportChildError() { 663 void ReportChildError() {
656 // In the case of failure in the child process write the errno and 664 // In the case of failure in the child process write the errno and
657 // the OS error message to the exec control pipe and exit. 665 // the OS error message to the exec control pipe and exit.
658 int child_errno = errno; 666 int child_errno = errno;
659 const int kBufferSize = 1024; 667 const int kBufferSize = 1024;
660 char error_buf[kBufferSize]; 668 char error_buf[kBufferSize];
661 char* os_error_message = Utils::StrError(errno, error_buf, kBufferSize); 669 char* os_error_message = Utils::StrError(errno, error_buf, kBufferSize);
662 int bytes_written = 670 int bytes_written = FDUtils::WriteToBlocking(
663 FDUtils::WriteToBlocking( 671 exec_control_[1], &child_errno, sizeof(child_errno));
664 exec_control_[1], &child_errno, sizeof(child_errno));
665 if (bytes_written == sizeof(child_errno)) { 672 if (bytes_written == sizeof(child_errno)) {
666 FDUtils::WriteToBlocking( 673 FDUtils::WriteToBlocking(
667 exec_control_[1], os_error_message, strlen(os_error_message) + 1); 674 exec_control_[1], os_error_message, strlen(os_error_message) + 1);
668 } 675 }
669 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); 676 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
670 exit(1); 677 exit(1);
671 } 678 }
672 679
673 680
674 void ReportPid(int pid) { 681 void ReportPid(int pid) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 730
724 const char* path_; 731 const char* path_;
725 const char* working_directory_; 732 const char* working_directory_;
726 ProcessStartMode mode_; 733 ProcessStartMode mode_;
727 intptr_t* in_; 734 intptr_t* in_;
728 intptr_t* out_; 735 intptr_t* out_;
729 intptr_t* err_; 736 intptr_t* err_;
730 intptr_t* id_; 737 intptr_t* id_;
731 intptr_t* exit_event_; 738 intptr_t* exit_event_;
732 char** os_error_message_; 739 char** os_error_message_;
740
741 DISALLOW_ALLOCATION();
742 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
733 }; 743 };
734 744
735 745
736 int Process::Start(const char* path, 746 int Process::Start(const char* path,
737 char* arguments[], 747 char* arguments[],
738 intptr_t arguments_length, 748 intptr_t arguments_length,
739 const char* working_directory, 749 const char* working_directory,
740 char* environment[], 750 char* environment[],
741 intptr_t environment_length, 751 intptr_t environment_length,
742 ProcessStartMode mode, 752 ProcessStartMode mode,
(...skipping 15 matching lines...) Expand all
758 err, 768 err,
759 id, 769 id,
760 exit_event, 770 exit_event,
761 os_error_message); 771 os_error_message);
762 return starter.Start(); 772 return starter.Start();
763 } 773 }
764 774
765 775
766 class BufferList: public BufferListBase { 776 class BufferList: public BufferListBase {
767 public: 777 public:
778 BufferList() {}
779
768 bool Read(int fd, intptr_t available) { 780 bool Read(int fd, intptr_t available) {
769 // Read all available bytes. 781 // Read all available bytes.
770 while (available > 0) { 782 while (available > 0) {
771 if (free_size_ == 0) Allocate(); 783 if (free_size_ == 0) {
784 Allocate();
785 }
772 ASSERT(free_size_ > 0); 786 ASSERT(free_size_ > 0);
773 ASSERT(free_size_ <= kBufferSize); 787 ASSERT(free_size_ <= kBufferSize);
774 intptr_t block_size = dart::Utils::Minimum(free_size_, available); 788 intptr_t block_size = dart::Utils::Minimum(free_size_, available);
775 intptr_t bytes = TEMP_FAILURE_RETRY(read( 789 intptr_t bytes = TEMP_FAILURE_RETRY(read(
776 fd, 790 fd,
777 reinterpret_cast<void*>(FreeSpaceAddress()), 791 reinterpret_cast<void*>(FreeSpaceAddress()),
778 block_size)); 792 block_size));
779 if (bytes < 0) return false; 793 if (bytes < 0) {
794 return false;
795 }
780 data_size_ += bytes; 796 data_size_ += bytes;
781 free_size_ -= bytes; 797 free_size_ -= bytes;
782 available -= bytes; 798 available -= bytes;
783 } 799 }
784 return true; 800 return true;
785 } 801 }
802
803 private:
804 DISALLOW_COPY_AND_ASSIGN(BufferList);
786 }; 805 };
787 806
788 807
789 static bool CloseProcessBuffers(struct pollfd fds[3]) { 808 static bool CloseProcessBuffers(struct pollfd fds[3]) {
790 int e = errno; 809 int e = errno;
791 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); 810 VOID_TEMP_FAILURE_RETRY(close(fds[0].fd));
792 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); 811 VOID_TEMP_FAILURE_RETRY(close(fds[1].fd));
793 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); 812 VOID_TEMP_FAILURE_RETRY(close(fds[2].fd));
794 errno = e; 813 errno = e;
795 return false; 814 return false;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 int alive = 3; 846 int alive = 3;
828 while (alive > 0) { 847 while (alive > 0) {
829 // Blocking call waiting for events from the child process. 848 // Blocking call waiting for events from the child process.
830 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { 849 if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) {
831 return CloseProcessBuffers(fds); 850 return CloseProcessBuffers(fds);
832 } 851 }
833 852
834 // Process incoming data. 853 // Process incoming data.
835 int current_alive = alive; 854 int current_alive = alive;
836 for (int i = 0; i < current_alive; i++) { 855 for (int i = 0; i < current_alive; i++) {
837 if (fds[i].revents & POLLIN) { 856 if ((fds[i].revents & POLLIN) != 0) {
838 intptr_t avail = FDUtils::AvailableBytes(fds[i].fd); 857 intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
839 if (fds[i].fd == out) { 858 if (fds[i].fd == out) {
840 if (!out_data.Read(out, avail)) { 859 if (!out_data.Read(out, avail)) {
841 return CloseProcessBuffers(fds); 860 return CloseProcessBuffers(fds);
842 } 861 }
843 } else if (fds[i].fd == err) { 862 } else if (fds[i].fd == err) {
844 if (!err_data.Read(err, avail)) { 863 if (!err_data.Read(err, avail)) {
845 return CloseProcessBuffers(fds); 864 return CloseProcessBuffers(fds);
846 } 865 }
847 } else if (fds[i].fd == exit_event) { 866 } else if (fds[i].fd == exit_event) {
848 if (avail == 8) { 867 if (avail == 8) {
849 intptr_t b = TEMP_FAILURE_RETRY(read(exit_event, 868 intptr_t b = TEMP_FAILURE_RETRY(read(exit_event,
850 exit_code_data.bytes, 8)); 869 exit_code_data.bytes, 8));
851 if (b != 8) { 870 if (b != 8) {
852 return CloseProcessBuffers(fds); 871 return CloseProcessBuffers(fds);
853 } 872 }
854 } 873 }
855 } else { 874 } else {
856 UNREACHABLE(); 875 UNREACHABLE();
857 } 876 }
858 } 877 }
859 if (fds[i].revents & POLLHUP) { 878 if ((fds[i].revents & POLLHUP) != 0) {
860 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); 879 VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
861 alive--; 880 alive--;
862 if (i < alive) { 881 if (i < alive) {
863 fds[i] = fds[alive]; 882 fds[i] = fds[alive];
864 } 883 }
865 } 884 }
866 } 885 }
867 } 886 }
868 887
869 // All handles closed and all data read. 888 // All handles closed and all data read.
870 result->set_stdout_data(out_data.GetData()); 889 result->set_stdout_data(out_data.GetData());
871 result->set_stderr_data(err_data.GetData()); 890 result->set_stderr_data(err_data.GetData());
872 891
873 // Calculate the exit code. 892 // Calculate the exit code.
874 intptr_t exit_code = exit_code_data.ints[0]; 893 intptr_t exit_code = exit_code_data.ints[0];
875 intptr_t negative = exit_code_data.ints[1]; 894 intptr_t negative = exit_code_data.ints[1];
876 if (negative) exit_code = -exit_code; 895 if (negative) {
896 exit_code = -exit_code;
897 }
877 result->set_exit_code(exit_code); 898 result->set_exit_code(exit_code);
878 899
879 return true; 900 return true;
880 } 901 }
881 902
882 903
883 bool Process::Kill(intptr_t id, int signal) { 904 bool Process::Kill(intptr_t id, int signal) {
884 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); 905 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1);
885 } 906 }
886 907
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 949
929 950
930 intptr_t Process::SetSignalHandler(intptr_t signal) { 951 intptr_t Process::SetSignalHandler(intptr_t signal) {
931 bool found = false; 952 bool found = false;
932 for (int i = 0; i < kSignalsCount; i++) { 953 for (int i = 0; i < kSignalsCount; i++) {
933 if (kSignals[i] == signal) { 954 if (kSignals[i] == signal) {
934 found = true; 955 found = true;
935 break; 956 break;
936 } 957 }
937 } 958 }
938 if (!found) return -1; 959 if (!found) {
960 return -1;
961 }
939 int fds[2]; 962 int fds[2];
940 if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) { 963 if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) {
941 return -1; 964 return -1;
942 } 965 }
943 ThreadSignalBlocker blocker(kSignalsCount, kSignals); 966 ThreadSignalBlocker blocker(kSignalsCount, kSignals);
944 MutexLocker lock(signal_mutex); 967 MutexLocker lock(signal_mutex);
945 SignalInfo* handler = signal_handlers; 968 SignalInfo* handler = signal_handlers;
946 bool listen = true; 969 bool listen = true;
947 while (handler != NULL) { 970 while (handler != NULL) {
948 if (handler->signal() == signal) { 971 if (handler->signal() == signal) {
(...skipping 26 matching lines...) Expand all
975 998
976 void Process::ClearSignalHandler(intptr_t signal) { 999 void Process::ClearSignalHandler(intptr_t signal) {
977 ThreadSignalBlocker blocker(kSignalsCount, kSignals); 1000 ThreadSignalBlocker blocker(kSignalsCount, kSignals);
978 MutexLocker lock(signal_mutex); 1001 MutexLocker lock(signal_mutex);
979 SignalInfo* handler = signal_handlers; 1002 SignalInfo* handler = signal_handlers;
980 bool unlisten = true; 1003 bool unlisten = true;
981 while (handler != NULL) { 1004 while (handler != NULL) {
982 bool remove = false; 1005 bool remove = false;
983 if (handler->signal() == signal) { 1006 if (handler->signal() == signal) {
984 if (handler->port() == Dart_GetMainPortId()) { 1007 if (handler->port() == Dart_GetMainPortId()) {
985 if (signal_handlers == handler) signal_handlers = handler->next(); 1008 if (signal_handlers == handler) {
1009 signal_handlers = handler->next();
1010 }
986 handler->Unlink(); 1011 handler->Unlink();
987 remove = true; 1012 remove = true;
988 } else { 1013 } else {
989 unlisten = false; 1014 unlisten = false;
990 } 1015 }
991 } 1016 }
992 SignalInfo* next = handler->next(); 1017 SignalInfo* next = handler->next();
993 if (remove) delete handler; 1018 if (remove) {
1019 delete handler;
1020 }
994 handler = next; 1021 handler = next;
995 } 1022 }
996 if (unlisten) { 1023 if (unlisten) {
997 struct sigaction act; 1024 struct sigaction act;
998 bzero(&act, sizeof(act)); 1025 bzero(&act, sizeof(act));
999 act.sa_handler = SIG_DFL; 1026 act.sa_handler = SIG_DFL;
1000 sigaction(signal, &act, NULL); 1027 sigaction(signal, &act, NULL);
1001 } 1028 }
1002 } 1029 }
1003 1030
1004 } // namespace bin 1031 } // namespace bin
1005 } // namespace dart 1032 } // namespace dart
1006 1033
1007 #endif // defined(TARGET_OS_LINUX) 1034 #endif // defined(TARGET_OS_LINUX)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698