Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |