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

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

Issue 9307003: Changes to the process implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Close the wake-up handle at the right time. Created 8 years, 10 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 | Annotate | Revision Log
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 "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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 ProcessInfo* ProcessInfoList::active_processes_ = NULL; 99 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
94 dart::Mutex ProcessInfoList::mutex_; 100 dart::Mutex ProcessInfoList::mutex_;
95 101
96 102
97 // The exit code handler sets up a separate thread which is signalled 103 // The exit code handler sets up a separate thread which is signalled
98 // on SIGCHLD. That separate thread can then get the exit code from 104 // on SIGCHLD. That separate thread can then get the exit code from
99 // processes that have exited and communicate it to Dart through the 105 // processes that have exited and communicate it to Dart through the
100 // event loop. 106 // event loop.
101 class ExitCodeHandler { 107 class ExitCodeHandler {
102 public: 108 public:
109 static const char kTerminateByte = 1;
110
103 // Ensure that the ExitCodeHandler has been initialized. 111 // Ensure that the ExitCodeHandler has been initialized.
104 static bool EnsureInitialized() { 112 static bool EnsureInitialized() {
105 // Multiple isolates could be starting processes at the same 113 // Multiple isolates could be starting processes at the same
106 // time. Make sure that only one of them initializes the 114 // time. Make sure that only one of them initializes the
107 // ExitCodeHandler. 115 // ExitCodeHandler.
108 MutexLocker locker(&mutex_); 116 MutexLocker locker(&mutex_);
109 if (initialized_) { 117 if (initialized_) {
110 return true; 118 return true;
111 } 119 }
112 120
(...skipping 15 matching lines...) Expand all
128 initialized_ = true; 136 initialized_ = true;
129 return true; 137 return true;
130 } 138 }
131 139
132 // Get the write end of the pipe. 140 // Get the write end of the pipe.
133 static int WakeUpFd() { 141 static int WakeUpFd() {
134 ASSERT(initialized_); 142 ASSERT(initialized_);
135 return sig_chld_fds_[1]; 143 return sig_chld_fds_[1];
136 } 144 }
137 145
146 static void Terminate() {
147 MutexLocker locker(&mutex_);
148 if (!initialized_) {
149 return;
150 }
151 char data = ExitCodeHandler::kTerminateByte;
152 ssize_t result = TEMP_FAILURE_RETRY(write(WakeUpFd(), &data, 1));
153 if (result < 1) {
154 perror("Failed to write to wake-up fd in SIGCHLD handler");
155 }
156 }
157
138 private: 158 private:
139 // GetProcessExitCodes is called on a separate thread when a SIGCHLD 159 // GetProcessExitCodes is called on a separate thread when a SIGCHLD
140 // signal is received to retrieve the exit codes and post them to 160 // signal is received to retrieve the exit codes and post them to
141 // dart. 161 // dart.
142 static void GetProcessExitCodes() { 162 static void GetProcessExitCodes() {
143 pid_t pid = 0; 163 pid_t pid = 0;
144 int status = 0; 164 int status = 0;
145 while ((pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) { 165 while ((pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) {
146 int exit_code = 0; 166 int exit_code = 0;
147 int negative = 0; 167 int negative = 0;
148 if (WIFEXITED(status)) { 168 if (WIFEXITED(status)) {
149 exit_code = WEXITSTATUS(status); 169 exit_code = WEXITSTATUS(status);
150 } 170 }
151 if (WIFSIGNALED(status)) { 171 if (WIFSIGNALED(status)) {
152 exit_code = WTERMSIG(status); 172 exit_code = WTERMSIG(status);
153 negative = 1; 173 negative = 1;
154 } 174 }
155 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid); 175 intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(pid);
156 if (exit_code_fd != 0) { 176 if (exit_code_fd != 0) {
157 int message[3] = { pid, exit_code, negative }; 177 int message[2] = { exit_code, negative };
158 ssize_t result = 178 ssize_t result =
159 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message)); 179 FDUtils::WriteToBlocking(exit_code_fd, &message, sizeof(message));
160 if (result != sizeof(message) && errno != EPIPE) { 180 if (result != sizeof(message) && errno != EPIPE) {
161 perror("ExitHandler notification failed"); 181 perror("ExitHandler notification failed");
162 } 182 }
163 TEMP_FAILURE_RETRY(close(exit_code_fd)); 183 ProcessInfoList::RemoveProcess(pid);
164 } 184 }
165 } 185 }
166 } 186 }
167 187
168 188
169 // Entry point for the separate exit code handler thread started by 189 // Entry point for the separate exit code handler thread started by
170 // the ExitCodeHandler. 190 // the ExitCodeHandler.
171 static void ExitCodeHandlerEntry(uword param) { 191 static void ExitCodeHandlerEntry(uword param) {
172 struct pollfd pollfds; 192 struct pollfd pollfds;
173 pollfds.fd = param; 193 pollfds.fd = param;
174 pollfds.events |= POLLIN; 194 pollfds.events |= POLLIN;
175 while (true) { 195 while (true) {
176 int result = TEMP_FAILURE_RETRY(poll(&pollfds, 1, -1)); 196 int result = TEMP_FAILURE_RETRY(poll(&pollfds, 1, -1));
177 if (result == -1) { 197 if (result == -1) {
178 ASSERT(EAGAIN == EWOULDBLOCK); 198 ASSERT(EAGAIN == EWOULDBLOCK);
179 if (errno != EWOULDBLOCK) { 199 if (errno != EWOULDBLOCK) {
180 perror("ExitCodeHandler poll failed"); 200 perror("ExitCodeHandler poll failed");
181 } 201 }
182 } else { 202 } else {
183 // Read the byte from the wake-up fd. 203 // Read the byte from the wake-up fd.
184 ASSERT(result = 1); 204 ASSERT(result = 1);
185 intptr_t data = 0; 205 intptr_t data = 0;
186 ssize_t read_bytes = FDUtils::ReadFromBlocking(pollfds.fd, &data, 1); 206 ssize_t read_bytes = FDUtils::ReadFromBlocking(pollfds.fd, &data, 1);
187 if (read_bytes < 1) { 207 if (read_bytes < 1) {
188 perror("Failed to read from wake-up fd in exit-code handler"); 208 perror("Failed to read from wake-up fd in exit-code handler");
189 } 209 }
210 // Check if the ExitCodeHandler has been terminated.
211 if (data == ExitCodeHandler::kTerminateByte) {
212 return;
213 }
190 // Get the exit code from all processes that have died. 214 // Get the exit code from all processes that have died.
191 GetProcessExitCodes(); 215 GetProcessExitCodes();
192 } 216 }
193 } 217 }
194 } 218 }
195 219
196 static dart::Mutex mutex_; 220 static dart::Mutex mutex_;
197 static bool initialized_; 221 static bool initialized_;
198 static int sig_chld_fds_[2]; 222 static int sig_chld_fds_[2];
199 }; 223 };
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 504
481 bool Process::Kill(intptr_t id) { 505 bool Process::Kill(intptr_t id) {
482 int result = TEMP_FAILURE_RETRY(kill(id, SIGKILL)); 506 int result = TEMP_FAILURE_RETRY(kill(id, SIGKILL));
483 if (result == -1) { 507 if (result == -1) {
484 return false; 508 return false;
485 } 509 }
486 return true; 510 return true;
487 } 511 }
488 512
489 513
490 void Process::Exit(intptr_t id) { 514 void Process::TerminateExitCodeHandler() {
491 ProcessInfoList::RemoveProcess(id); 515 ExitCodeHandler::Terminate();
492 } 516 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698