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

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

Issue 9315037: Wait for exit-code thread to terminate before terminating main. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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
« no previous file with comments | « runtime/bin/process.h ('k') | runtime/bin/process_macos.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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>
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 ProcessInfo* ProcessInfoList::active_processes_ = NULL; 94 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
95 dart::Mutex ProcessInfoList::mutex_; 95 dart::Mutex ProcessInfoList::mutex_;
96 96
97 97
98 // The exit code handler sets up a separate thread which is signalled 98 // 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 99 // on SIGCHLD. That separate thread can then get the exit code from
100 // processes that have exited and communicate it to Dart through the 100 // processes that have exited and communicate it to Dart through the
101 // event loop. 101 // event loop.
102 class ExitCodeHandler { 102 class ExitCodeHandler {
103 public: 103 public:
104 static const uint8_t kThreadTerminateByte = 1;
Ivan Posva 2012/02/01 18:09:24 Why public? This is only used from within ExitCode
Mads Ager (google) 2012/02/01 18:15:18 Good point. Done.
105
104 // Ensure that the ExitCodeHandler has been initialized. 106 // Ensure that the ExitCodeHandler has been initialized.
105 static bool EnsureInitialized() { 107 static bool EnsureInitialized() {
106 // Multiple isolates could be starting processes at the same 108 // Multiple isolates could be starting processes at the same
107 // time. Make sure that only one of them initializes the 109 // time. Make sure that only one of them initializes the
108 // ExitCodeHandler. 110 // ExitCodeHandler.
109 MutexLocker locker(&mutex_); 111 MutexLocker locker(&mutex_);
110 if (initialized_) { 112 if (initialized_) {
111 return true; 113 return true;
112 } 114 }
113 115
(...skipping 15 matching lines...) Expand all
129 initialized_ = true; 131 initialized_ = true;
130 return true; 132 return true;
131 } 133 }
132 134
133 // Get the write end of the pipe. 135 // Get the write end of the pipe.
134 static int WakeUpFd() { 136 static int WakeUpFd() {
135 ASSERT(initialized_); 137 ASSERT(initialized_);
136 return sig_chld_fds_[1]; 138 return sig_chld_fds_[1];
137 } 139 }
138 140
141 static void TerminateExitCodeThread() {
142 MutexLocker locker(&mutex_);
143 if (!initialized_) {
144 return;
145 }
146
147 uint8_t data = kThreadTerminateByte;
148 ssize_t result =
149 TEMP_FAILURE_RETRY(write(ExitCodeHandler::WakeUpFd(), &data, 1));
150 if (result < 1) {
151 perror("Failed to write to wake-up fd to terminate exit code thread");
152 }
153
154 {
155 MonitorLocker terminate_locker(&thread_terminate_monitor_);
156 while (!thread_terminated_) {
157 terminate_locker.Wait();
158 }
159 }
160 }
161
162 static void ExitCodeThreadTerminated() {
163 MonitorLocker locker(&thread_terminate_monitor_);
164 thread_terminated_ = true;
165 locker.Notify();
166 }
167
139 private: 168 private:
140 // GetProcessExitCodes is called on a separate thread when a SIGCHLD 169 // GetProcessExitCodes is called on a separate thread when a SIGCHLD
141 // signal is received to retrieve the exit codes and post them to 170 // signal is received to retrieve the exit codes and post them to
142 // dart. 171 // dart.
143 static void GetProcessExitCodes() { 172 static void GetProcessExitCodes() {
144 pid_t pid = 0; 173 pid_t pid = 0;
145 int status = 0; 174 int status = 0;
146 while ((pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) { 175 while ((pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) {
147 int exit_code = 0; 176 int exit_code = 0;
148 int negative = 0; 177 int negative = 0;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 perror("ExitCodeHandler poll failed"); 210 perror("ExitCodeHandler poll failed");
182 } 211 }
183 } else { 212 } else {
184 // Read the byte from the wake-up fd. 213 // Read the byte from the wake-up fd.
185 ASSERT(result = 1); 214 ASSERT(result = 1);
186 intptr_t data = 0; 215 intptr_t data = 0;
187 ssize_t read_bytes = FDUtils::ReadFromBlocking(pollfds.fd, &data, 1); 216 ssize_t read_bytes = FDUtils::ReadFromBlocking(pollfds.fd, &data, 1);
188 if (read_bytes < 1) { 217 if (read_bytes < 1) {
189 perror("Failed to read from wake-up fd in exit-code handler"); 218 perror("Failed to read from wake-up fd in exit-code handler");
190 } 219 }
220 if (data == ExitCodeHandler::kThreadTerminateByte) {
221 ExitCodeThreadTerminated();
222 return;
223 }
191 // Get the exit code from all processes that have died. 224 // Get the exit code from all processes that have died.
192 GetProcessExitCodes(); 225 GetProcessExitCodes();
193 } 226 }
194 } 227 }
195 } 228 }
196 229
197 static dart::Mutex mutex_; 230 static dart::Mutex mutex_;
198 static bool initialized_; 231 static bool initialized_;
199 static int sig_chld_fds_[2]; 232 static int sig_chld_fds_[2];
233 static bool thread_terminated_;
234 static dart::Monitor thread_terminate_monitor_;
200 }; 235 };
201 236
202 237
203 dart::Mutex ExitCodeHandler::mutex_; 238 dart::Mutex ExitCodeHandler::mutex_;
204 bool ExitCodeHandler::initialized_ = false; 239 bool ExitCodeHandler::initialized_ = false;
205 int ExitCodeHandler::sig_chld_fds_[2] = { 0, 0 }; 240 int ExitCodeHandler::sig_chld_fds_[2] = { 0, 0 };
241 bool ExitCodeHandler::thread_terminated_ = false;
242 dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
206 243
207 244
208 static char* SafeStrNCpy(char* dest, const char* src, size_t n) { 245 static char* SafeStrNCpy(char* dest, const char* src, size_t n) {
209 strncpy(dest, src, n); 246 strncpy(dest, src, n);
210 dest[n - 1] = '\0'; 247 dest[n - 1] = '\0';
211 return dest; 248 return dest;
212 } 249 }
213 250
214 251
215 static void SetChildOsErrorMessage(char* os_error_message, 252 static void SetChildOsErrorMessage(char* os_error_message,
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 if (result == -1) { 521 if (result == -1) {
485 return false; 522 return false;
486 } 523 }
487 return true; 524 return true;
488 } 525 }
489 526
490 527
491 void Process::Exit(intptr_t id) { 528 void Process::Exit(intptr_t id) {
492 ProcessInfoList::RemoveProcess(id); 529 ProcessInfoList::RemoveProcess(id);
493 } 530 }
531
532
533 void Process::TerminateExitCodeHandler() {
534 ExitCodeHandler::TerminateExitCodeThread();
535 }
OLDNEW
« no previous file with comments | « runtime/bin/process.h ('k') | runtime/bin/process_macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698