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

Side by Side Diff: runtime/vm/message_handler.cc

Issue 1371193005: VM restart + shutdown fixes (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix ups Created 5 years, 2 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
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 "vm/message_handler.h" 5 #include "vm/message_handler.h"
6 6
7 #include "vm/dart.h" 7 #include "vm/dart.h"
8 #include "vm/lockers.h" 8 #include "vm/lockers.h"
9 #include "vm/os.h" 9 #include "vm/os.h"
10 #include "vm/port.h" 10 #include "vm/port.h"
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 Message* MessageHandler::DequeueMessage(Message::Priority min_priority) { 143 Message* MessageHandler::DequeueMessage(Message::Priority min_priority) {
144 // TODO(turnidge): Add assert that monitor_ is held here. 144 // TODO(turnidge): Add assert that monitor_ is held here.
145 Message* message = oob_queue_->Dequeue(); 145 Message* message = oob_queue_->Dequeue();
146 if ((message == NULL) && (min_priority < Message::kOOBPriority)) { 146 if ((message == NULL) && (min_priority < Message::kOOBPriority)) {
147 message = queue_->Dequeue(); 147 message = queue_->Dequeue();
148 } 148 }
149 return message; 149 return message;
150 } 150 }
151 151
152 152
153 bool MessageHandler::HandleMessages(bool allow_normal_messages, 153 void MessageHandler::ClearOOBQueue() {
154 bool allow_multiple_normal_messages) { 154 oob_queue_->Clear();
155 }
156
157
158 MessageHandler::MessageStatus MessageHandler::HandleMessages(
159 bool allow_normal_messages,
160 bool allow_multiple_normal_messages) {
161 // TODO(turnidge): Add assert that monitor_ is held here.
162
155 // If isolate() returns NULL StartIsolateScope does nothing. 163 // If isolate() returns NULL StartIsolateScope does nothing.
156 StartIsolateScope start_isolate(isolate()); 164 StartIsolateScope start_isolate(isolate());
157 165
158 // ThreadInterrupter may have gone to sleep while waiting for 166 // ThreadInterrupter may have gone to sleep while waiting for
159 // an isolate to start handling messages. 167 // an isolate to start handling messages.
160 ThreadInterrupter::WakeUp(); 168 ThreadInterrupter::WakeUp();
161 169
162 // TODO(turnidge): Add assert that monitor_ is held here. 170 MessageStatus status = kOK;
163 bool result = true; 171 Message::Priority min_priority = ((allow_normal_messages && !paused())
164 Message::Priority min_priority = (allow_normal_messages && !paused()) ? 172 ? Message::kNormalPriority
165 Message::kNormalPriority : Message::kOOBPriority; 173 : Message::kOOBPriority);
166 Message* message = DequeueMessage(min_priority); 174 Message* message = DequeueMessage(min_priority);
167 while (message != NULL) { 175 while (message != NULL) {
168 intptr_t message_len = message->len(); 176 intptr_t message_len = message->len();
169 if (FLAG_trace_isolates) { 177 if (FLAG_trace_isolates) {
170 OS::Print("[<] Handling message:\n" 178 OS::Print("[<] Handling message:\n"
171 "\tlen: %" Pd "\n" 179 "\tlen: %" Pd "\n"
172 "\thandler: %s\n" 180 "\thandler: %s\n"
173 "\tport: %" Pd64 "\n", 181 "\tport: %" Pd64 "\n",
174 message_len, name(), message->dest_port()); 182 message_len, name(), message->dest_port());
175 } 183 }
176 184
177 // Release the monitor_ temporarily while we handle the message. 185 // Release the monitor_ temporarily while we handle the message.
178 // The monitor was acquired in MessageHandler::TaskCallback(). 186 // The monitor was acquired in MessageHandler::TaskCallback().
179 monitor_.Exit(); 187 monitor_.Exit();
180 Message::Priority saved_priority = message->priority(); 188 Message::Priority saved_priority = message->priority();
181 Dart_Port saved_dest_port = message->dest_port(); 189 Dart_Port saved_dest_port = message->dest_port();
182 result = HandleMessage(message); 190 status = HandleMessage(message);
183 message = NULL; // May be deleted by now. 191 message = NULL; // May be deleted by now.
184 monitor_.Enter(); 192 monitor_.Enter();
185 if (FLAG_trace_isolates) { 193 if (FLAG_trace_isolates) {
186 OS::Print("[.] Message handled:\n" 194 OS::Print("[.] Message handled:\n"
187 "\tlen: %" Pd "\n" 195 "\tlen: %" Pd "\n"
188 "\thandler: %s\n" 196 "\thandler: %s\n"
189 "\tport: %" Pd64 "\n", 197 "\tport: %" Pd64 "\n",
190 message_len, name(), saved_dest_port); 198 message_len, name(), saved_dest_port);
191 } 199 }
192 if (!result) { 200 // If we are shutting down, do not process any more messages.
193 // If we hit an error, we're done processing messages. 201 if (status == kShutdown) {
202 ClearOOBQueue();
194 break; 203 break;
195 } 204 }
205
196 // Some callers want to process only one normal message and then quit. At 206 // Some callers want to process only one normal message and then quit. At
197 // the same time it is OK to process multiple OOB messages. 207 // the same time it is OK to process multiple OOB messages.
198 if ((saved_priority == Message::kNormalPriority) && 208 if ((saved_priority == Message::kNormalPriority) &&
199 !allow_multiple_normal_messages) { 209 !allow_multiple_normal_messages) {
200 break; 210 // We processed one normal message. Allow no more.
211 allow_normal_messages = false;
201 } 212 }
202 213
203 // Reevaluate the minimum allowable priority as the paused state might 214 // Reevaluate the minimum allowable priority. The paused state
204 // have changed as part of handling the message. 215 // may have changed as part of handling the message. We may also
205 min_priority = (allow_normal_messages && !paused()) ? 216 // have encountered an error during message processsing.
206 Message::kNormalPriority : Message::kOOBPriority; 217 //
218 // Even if we encounter an error, we still process pending OOB
219 // messages so that we don't lose the message notification.
220 min_priority = (((status == kOK) && allow_normal_messages && !paused())
221 ? Message::kNormalPriority
222 : Message::kOOBPriority);
207 message = DequeueMessage(min_priority); 223 message = DequeueMessage(min_priority);
208 } 224 }
209 return result; 225 return status;
210 } 226 }
211 227
212 228
213 bool MessageHandler::HandleNextMessage() { 229 MessageHandler::MessageStatus MessageHandler::HandleNextMessage() {
214 // We can only call HandleNextMessage when this handler is not 230 // We can only call HandleNextMessage when this handler is not
215 // assigned to a thread pool. 231 // assigned to a thread pool.
216 MonitorLocker ml(&monitor_); 232 MonitorLocker ml(&monitor_);
217 ASSERT(pool_ == NULL); 233 ASSERT(pool_ == NULL);
218 #if defined(DEBUG) 234 #if defined(DEBUG)
219 CheckAccess(); 235 CheckAccess();
220 #endif 236 #endif
221 return HandleMessages(true, false); 237 return HandleMessages(true, false);
222 } 238 }
223 239
224 240
225 bool MessageHandler::HandleOOBMessages() { 241 MessageHandler::MessageStatus MessageHandler::HandleOOBMessages() {
226 if (!oob_message_handling_allowed_) { 242 if (!oob_message_handling_allowed_) {
227 return true; 243 return kOK;
228 } 244 }
229 MonitorLocker ml(&monitor_); 245 MonitorLocker ml(&monitor_);
230 #if defined(DEBUG) 246 #if defined(DEBUG)
231 CheckAccess(); 247 CheckAccess();
232 #endif 248 #endif
233 return HandleMessages(false, false); 249 return HandleMessages(false, false);
234 } 250 }
235 251
236 252
237 bool MessageHandler::HasOOBMessages() { 253 bool MessageHandler::HasOOBMessages() {
238 MonitorLocker ml(&monitor_); 254 MonitorLocker ml(&monitor_);
239 return !oob_queue_->IsEmpty(); 255 return !oob_queue_->IsEmpty();
240 } 256 }
241 257
242 258
259 bool ShouldPause(MessageHandler::MessageStatus status) {
Cutch 2015/10/05 18:10:46 static
turnidge 2015/10/05 22:18:24 Done.
260 // If we are restarting or shutting down, we do not want to honor
261 // pause_on_start or pause_on_exit.
262 return (status != MessageHandler::kRestart &&
263 status != MessageHandler::kShutdown);
264 }
265
266
243 void MessageHandler::TaskCallback() { 267 void MessageHandler::TaskCallback() {
244 ASSERT(Isolate::Current() == NULL); 268 ASSERT(Isolate::Current() == NULL);
245 bool ok = true; 269 MessageStatus status = kOK;
246 bool run_end_callback = false; 270 bool run_end_callback = false;
247 { 271 {
272 // We will occasionally release and reacquire this monitor in this
273 // function. Whenever we reacquire the monitor we *must* process
274 // all pending OOB messages, or we may miss a request for vm
275 // shutdown.
248 MonitorLocker ml(&monitor_); 276 MonitorLocker ml(&monitor_);
249 // Initialize the message handler by running its start function,
250 // if we have one. For an isolate, this will run the isolate's
251 // main() function.
252 if (pause_on_start()) { 277 if (pause_on_start()) {
253 if (!paused_on_start_) { 278 if (!paused_on_start_) {
254 // Temporarily drop the lock when calling out to NotifyPauseOnStart. 279 // Temporarily release the monitor when calling out to
255 // This avoids a dead lock that can occur when this message handler 280 // NotifyPauseOnStart. This avoids a dead lock that can occur
256 // tries to post a message while a message is being posted to it. 281 // when this message handler tries to post a message while a
282 // message is being posted to it.
257 paused_on_start_ = true; 283 paused_on_start_ = true;
258 paused_timestamp_ = OS::GetCurrentTimeMillis(); 284 paused_timestamp_ = OS::GetCurrentTimeMillis();
259 monitor_.Exit(); 285 monitor_.Exit();
260 NotifyPauseOnStart(); 286 NotifyPauseOnStart();
261 monitor_.Enter(); 287 monitor_.Enter();
262 } 288 }
263 // More messages may have come in while we released monitor_. 289 // More messages may have come in before we (re)acquired the monitor.
264 HandleMessages(false, false); 290 status = HandleMessages(false, false);
265 if (pause_on_start()) { 291 if (ShouldPause(status) && pause_on_start()) {
266 // Still paused. 292 // Still paused.
267 ASSERT(oob_queue_->IsEmpty()); 293 ASSERT(oob_queue_->IsEmpty());
268 task_ = NULL; // No task in queue. 294 task_ = NULL; // No task in queue.
269 return; 295 return;
270 } else { 296 } else {
271 paused_on_start_ = false; 297 paused_on_start_ = false;
272 paused_timestamp_ = -1; 298 paused_timestamp_ = -1;
273 } 299 }
274 } 300 }
275 301
276 if (start_callback_) { 302 if (status == kOK) {
277 // Release the monitor_ temporarily while we call the start callback. 303 if (start_callback_) {
278 // The monitor was acquired with the MonitorLocker above. 304 // Initialize the message handler by running its start function,
279 monitor_.Exit(); 305 // if we have one. For an isolate, this will run the isolate's
280 ok = start_callback_(callback_data_); 306 // main() function.
281 ASSERT(Isolate::Current() == NULL); 307 //
282 start_callback_ = NULL; 308 // Release the monitor_ temporarily while we call the start callback.
283 monitor_.Enter(); 309 monitor_.Exit();
310 status = start_callback_(callback_data_);
311 ASSERT(Isolate::Current() == NULL);
312 start_callback_ = NULL;
313 monitor_.Enter();
314 }
315
316 // Handle any pending messages for this message handler.
317 if (status != kShutdown) {
318 status = HandleMessages((status == kOK), true);
319 }
284 } 320 }
285 321
286 // Handle any pending messages for this message handler. 322 // The isolate exits when it encounters an error or when it no
287 if (ok) { 323 // longer has live ports.
288 ok = HandleMessages(true, true); 324 if (status != kOK || !HasLivePorts()) {
289 } 325 if (ShouldPause(status) && pause_on_exit()) {
290
291 if (!ok || !HasLivePorts()) {
292 if (pause_on_exit()) {
293 if (!paused_on_exit_) { 326 if (!paused_on_exit_) {
294 if (FLAG_trace_service_pause_events) { 327 if (FLAG_trace_service_pause_events) {
295 OS::PrintErr("Isolate %s paused before exiting. " 328 OS::PrintErr("Isolate %s paused before exiting. "
296 "Use the Observatory to release it.\n", name()); 329 "Use the Observatory to release it.\n", name());
297 } 330 }
298 // Temporarily drop the lock when calling out to NotifyPauseOnExit. 331 // Temporarily release the monitor when calling out to
299 // This avoids a dead lock that can occur when this message handler 332 // NotifyPauseOnExit. This avoids a dead lock that can
300 // tries to post a message while a message is being posted to it. 333 // occur when this message handler tries to post a message
334 // while a message is being posted to it.
301 paused_on_exit_ = true; 335 paused_on_exit_ = true;
302 paused_timestamp_ = OS::GetCurrentTimeMillis(); 336 paused_timestamp_ = OS::GetCurrentTimeMillis();
303 monitor_.Exit(); 337 monitor_.Exit();
304 NotifyPauseOnExit(); 338 NotifyPauseOnExit();
305 monitor_.Enter(); 339 monitor_.Enter();
340
341 // More messages may have come in while we released the monitor.
342 HandleMessages(false, false);
306 } 343 }
307 // More messages may have come in while we released monitor_. 344 if (ShouldPause(status) && pause_on_exit()) {
308 HandleMessages(false, false);
309 if (pause_on_exit()) {
310 // Still paused. 345 // Still paused.
311 ASSERT(oob_queue_->IsEmpty()); 346 ASSERT(oob_queue_->IsEmpty());
312 task_ = NULL; // No task in queue. 347 task_ = NULL; // No task in queue.
313 return; 348 return;
314 } else { 349 } else {
315 paused_on_exit_ = false; 350 paused_on_exit_ = false;
316 paused_timestamp_ = -1; 351 paused_timestamp_ = -1;
317 } 352 }
318 } 353 }
319 if (FLAG_trace_isolates) { 354 if (FLAG_trace_isolates) {
320 OS::Print("[-] Stopping message handler (%s):\n" 355 OS::Print("[-] Stopping message handler (%s):\n"
321 "\thandler: %s\n", 356 "\thandler: %s\n",
322 (ok ? "no live ports" : "error"), 357 ((status == kOK) ? "no live ports" : "error"),
zra 2015/10/05 16:56:47 It might also be useful to know which error it was
Cutch 2015/10/05 18:10:46 +1
turnidge 2015/10/05 22:18:24 Done. But I was sad to have to import object.h --
323 name()); 358 name());
324 } 359 }
325 pool_ = NULL; 360 pool_ = NULL;
326 run_end_callback = true; 361 run_end_callback = true;
327 } 362 }
328 363
329 // Clear the task_ last. This allows other tasks to potentially start 364 // Clear the task_ last. This allows other tasks to potentially start
330 // for this message handler. 365 // for this message handler.
331 ASSERT(oob_queue_->IsEmpty()); 366 ASSERT(oob_queue_->IsEmpty());
332 task_ = NULL; 367 task_ = NULL;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 443
409 444
410 void MessageHandler::AcquireQueues(AcquiredQueues* acquired_queues) { 445 void MessageHandler::AcquireQueues(AcquiredQueues* acquired_queues) {
411 ASSERT(acquired_queues != NULL); 446 ASSERT(acquired_queues != NULL);
412 // No double dipping. 447 // No double dipping.
413 ASSERT(acquired_queues->handler_ == NULL); 448 ASSERT(acquired_queues->handler_ == NULL);
414 acquired_queues->Reset(this); 449 acquired_queues->Reset(this);
415 } 450 }
416 451
417 } // namespace dart 452 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698