| 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 "bin/process.h" | 5 #include "bin/process.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <poll.h> | 9 #include <poll.h> |
| 10 #include <signal.h> | 10 #include <signal.h> |
| 11 #include <stdio.h> | 11 #include <stdio.h> |
| 12 #include <stdlib.h> | 12 #include <stdlib.h> |
| 13 #include <string.h> | 13 #include <string.h> |
| 14 #include <unistd.h> | 14 #include <unistd.h> |
| 15 | 15 |
| 16 #include "bin/fdutils.h" | 16 #include "bin/fdutils.h" |
| 17 #include "bin/thread.h" | 17 #include "bin/thread.h" |
| 18 | 18 |
| 19 | 19 |
| 20 // ProcessInfo is used to map a process id to the file descriptor for | 20 // ProcessInfo is used to map a process id to the file descriptor for |
| 21 // the pipe used to communicate the exit code of the process to Dart. | 21 // the pipe used to communicate the exit code of the process to Dart. |
| 22 // ProcessInfo objects are kept in the static singly-linked | 22 // ProcessInfo objects are kept in the static singly-linked |
| 23 // ProcessInfoList. | 23 // ProcessInfoList. |
| 24 class ProcessInfo { | 24 class ProcessInfo { |
| 25 public: | 25 public: |
| 26 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } | 26 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } |
| 27 ~ProcessInfo() { |
| 28 int closed = TEMP_FAILURE_RETRY(close(fd_)); |
| 29 if (closed != 0) { |
| 30 FATAL("Failed to close process exit code pipe"); |
| 31 } |
| 32 } |
| 27 pid_t pid() { return pid_; } | 33 pid_t pid() { return pid_; } |
| 28 intptr_t fd() { return fd_; } | 34 intptr_t fd() { return fd_; } |
| 29 ProcessInfo* next() { return next_; } | 35 ProcessInfo* next() { return next_; } |
| 30 void set_next(ProcessInfo* info) { next_ = info; } | 36 void set_next(ProcessInfo* info) { next_ = info; } |
| 31 | 37 |
| 32 private: | 38 private: |
| 33 pid_t pid_; | 39 pid_t pid_; |
| 34 intptr_t fd_; | 40 intptr_t fd_; |
| 35 ProcessInfo* next_; | 41 ProcessInfo* next_; |
| 36 }; | 42 }; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 int negative = 0; | 185 int negative = 0; |
| 180 if (WIFEXITED(status)) { | 186 if (WIFEXITED(status)) { |
| 181 exit_code = WEXITSTATUS(status); | 187 exit_code = WEXITSTATUS(status); |
| 182 } | 188 } |
| 183 if (WIFSIGNALED(status)) { | 189 if (WIFSIGNALED(status)) { |
| 184 exit_code = WTERMSIG(status); | 190 exit_code = WTERMSIG(status); |
| 185 negative = 1; | 191 negative = 1; |
| 186 } | 192 } |
| 187 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); | 193 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); |
| 188 if (exit_code_fd != 0) { | 194 if (exit_code_fd != 0) { |
| 189 int message[3] = { pid, exit_code, negative }; | 195 int message[2] = { exit_code, negative }; |
| 190 ssize_t result = | 196 ssize_t result = |
| 191 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); | 197 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); |
| 192 if (result != sizeof(message) && errno != EPIPE) { | 198 // If the process has been closed, the read end of the exit |
| 193 perror("ExitHandler notification failed"); | 199 // pipe has been closed. It is therefore not a problem that |
| 200 // writennnj fails with a broken pipe error. Other errors should |
| 201 // not happen. |
| 202 if (result != -1 && result != sizeof(message)) { |
| 203 FATAL("Failed to write entire process exit message"); |
| 204 } else if (result == -1 && errno != EPIPE) { |
| 205 FATAL1("Failed to write exit code: %d", errno); |
| 194 } | 206 } |
| 195 TEMP_FAILURE_RETRY(close(exit_code_fd)); | 207 ProcessInfoList::RemoveProcess(pid); |
| 196 } | 208 } |
| 197 } | 209 } |
| 198 } | 210 } |
| 199 | 211 |
| 200 | 212 |
| 201 // Entry point for the separate exit code handler thread started by | 213 // Entry point for the separate exit code handler thread started by |
| 202 // the ExitCodeHandler. | 214 // the ExitCodeHandler. |
| 203 static void ExitCodeHandlerEntry(uword param) { | 215 static void ExitCodeHandlerEntry(uword param) { |
| 204 struct pollfd pollfds; | 216 struct pollfd pollfds; |
| 205 pollfds.fd = param; | 217 pollfds.fd = param; |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 | 532 |
| 521 bool Process::Kill(intptr_t id) { | 533 bool Process::Kill(intptr_t id) { |
| 522 int result = TEMP_FAILURE_RETRY(kill(id, SIGKILL)); | 534 int result = TEMP_FAILURE_RETRY(kill(id, SIGKILL)); |
| 523 if (result == -1) { | 535 if (result == -1) { |
| 524 return false; | 536 return false; |
| 525 } | 537 } |
| 526 return true; | 538 return true; |
| 527 } | 539 } |
| 528 | 540 |
| 529 | 541 |
| 530 void Process::Exit(intptr_t id) { | |
| 531 ProcessInfoList::RemoveProcess(id); | |
| 532 } | |
| 533 | |
| 534 | |
| 535 void Process::TerminateExitCodeHandler() { | 542 void Process::TerminateExitCodeHandler() { |
| 536 ExitCodeHandler::TerminateExitCodeThread(); | 543 ExitCodeHandler::TerminateExitCodeThread(); |
| 537 } | 544 } |
| OLD | NEW |