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

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

Powered by Google App Engine
This is Rietveld 408576698