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