OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_LINUX) | 6 #if defined(TARGET_OS_LINUX) |
7 | 7 |
8 #include "bin/process.h" | 8 #include "bin/process.h" |
9 | 9 |
10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
11 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
12 #include <poll.h> // NOLINT | 12 #include <poll.h> // NOLINT |
13 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
14 #include <stdlib.h> // NOLINT | 14 #include <stdlib.h> // NOLINT |
15 #include <string.h> // NOLINT | 15 #include <string.h> // NOLINT |
16 #include <sys/wait.h> // NOLINT | 16 #include <sys/wait.h> // NOLINT |
17 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
18 | 18 |
19 #include "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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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) |
OLD | NEW |