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 |