| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ipc/ipc_sync_channel.h" | 5 #include "ipc/ipc_sync_channel.h" |
| 6 | 6 |
| 7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/thread_local.h" | 9 #include "base/thread_local.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 } | 336 } |
| 337 | 337 |
| 338 void SyncChannel::SyncContext::CancelPendingSends() { | 338 void SyncChannel::SyncContext::CancelPendingSends() { |
| 339 AutoLock auto_lock(deserializers_lock_); | 339 AutoLock auto_lock(deserializers_lock_); |
| 340 PendingSyncMessageQueue::iterator iter; | 340 PendingSyncMessageQueue::iterator iter; |
| 341 for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) | 341 for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) |
| 342 iter->done_event->Signal(); | 342 iter->done_event->Signal(); |
| 343 } | 343 } |
| 344 | 344 |
| 345 void SyncChannel::SyncContext::OnWaitableEventSignaled(WaitableEvent* event) { | 345 void SyncChannel::SyncContext::OnWaitableEventSignaled(WaitableEvent* event) { |
| 346 DCHECK(event == shutdown_event_); | 346 if (event == shutdown_event_) { |
| 347 // Process shut down before we can get a reply to a synchronous message. | 347 // Process shut down before we can get a reply to a synchronous message. |
| 348 // Cancel pending Send calls, which will end up setting the send done event. | 348 // Cancel pending Send calls, which will end up setting the send done event. |
| 349 CancelPendingSends(); | 349 CancelPendingSends(); |
| 350 } else { |
| 351 // We got the reply, timed out or the process shutdown. |
| 352 DCHECK(event == GetSendDoneEvent()); |
| 353 MessageLoop::current()->Quit(); |
| 354 } |
| 350 } | 355 } |
| 351 | 356 |
| 352 | 357 |
| 353 SyncChannel::SyncChannel( | 358 SyncChannel::SyncChannel( |
| 354 const std::string& channel_id, Channel::Mode mode, | 359 const std::string& channel_id, Channel::Mode mode, |
| 355 Channel::Listener* listener, MessageFilter* filter, | 360 Channel::Listener* listener, MessageFilter* filter, |
| 356 MessageLoop* ipc_message_loop, bool create_pipe_now, | 361 MessageLoop* ipc_message_loop, bool create_pipe_now, |
| 357 WaitableEvent* shutdown_event) | 362 WaitableEvent* shutdown_event) |
| 358 : ChannelProxy( | 363 : ChannelProxy( |
| 359 channel_id, mode, ipc_message_loop, | 364 channel_id, mode, ipc_message_loop, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 if (timeout_ms != base::kNoTimeout) { | 406 if (timeout_ms != base::kNoTimeout) { |
| 402 // We use the sync message id so that when a message times out, we don't | 407 // We use the sync message id so that when a message times out, we don't |
| 403 // confuse it with another send that is either above/below this Send in | 408 // confuse it with another send that is either above/below this Send in |
| 404 // the call stack. | 409 // the call stack. |
| 405 context->ipc_message_loop()->PostDelayedTask(FROM_HERE, | 410 context->ipc_message_loop()->PostDelayedTask(FROM_HERE, |
| 406 NewRunnableMethod(context.get(), | 411 NewRunnableMethod(context.get(), |
| 407 &SyncContext::OnSendTimeout, message_id), timeout_ms); | 412 &SyncContext::OnSendTimeout, message_id), timeout_ms); |
| 408 } | 413 } |
| 409 | 414 |
| 410 // Wait for reply, or for any other incoming synchronous messages. | 415 // Wait for reply, or for any other incoming synchronous messages. |
| 411 WaitForReply(pump_messages_event); | 416 // *this* might get deleted, so only call static functions at this point. |
| 417 WaitForReply(context, pump_messages_event); |
| 412 | 418 |
| 413 return context->Pop(); | 419 return context->Pop(); |
| 414 } | 420 } |
| 415 | 421 |
| 416 void SyncChannel::WaitForReply(WaitableEvent* pump_messages_event) { | 422 void SyncChannel::WaitForReply( |
| 423 SyncContext* context, WaitableEvent* pump_messages_event) { |
| 417 while (true) { | 424 while (true) { |
| 418 WaitableEvent* objects[] = { | 425 WaitableEvent* objects[] = { |
| 419 sync_context()->GetDispatchEvent(), | 426 context->GetDispatchEvent(), |
| 420 sync_context()->GetSendDoneEvent(), | 427 context->GetSendDoneEvent(), |
| 421 pump_messages_event | 428 pump_messages_event |
| 422 }; | 429 }; |
| 423 | 430 |
| 424 unsigned count = pump_messages_event ? 3: 2; | 431 unsigned count = pump_messages_event ? 3: 2; |
| 425 size_t result = WaitableEvent::WaitMany(objects, count); | 432 size_t result = WaitableEvent::WaitMany(objects, count); |
| 426 if (result == 0 /* dispatch event */) { | 433 if (result == 0 /* dispatch event */) { |
| 427 // We're waiting for a reply, but we received a blocking synchronous | 434 // We're waiting for a reply, but we received a blocking synchronous |
| 428 // call. We must process it or otherwise a deadlock might occur. | 435 // call. We must process it or otherwise a deadlock might occur. |
| 429 sync_context()->GetDispatchEvent()->Reset(); | 436 context->GetDispatchEvent()->Reset(); |
| 430 sync_context()->DispatchMessages(); | 437 context->DispatchMessages(); |
| 431 continue; | 438 continue; |
| 432 } | 439 } |
| 433 | 440 |
| 434 if (result == 2 /* pump_messages_event */) | 441 if (result == 2 /* pump_messages_event */) |
| 435 WaitForReplyWithNestedMessageLoop(); // Start a nested message loop. | 442 WaitForReplyWithNestedMessageLoop(context); // Run a nested message loop. |
| 436 | 443 |
| 437 break; | 444 break; |
| 438 } | 445 } |
| 439 } | 446 } |
| 440 | 447 |
| 441 void SyncChannel::WaitForReplyWithNestedMessageLoop() { | 448 void SyncChannel::WaitForReplyWithNestedMessageLoop(SyncContext* context) { |
| 442 base::WaitableEventWatcher send_done_watcher; | 449 base::WaitableEventWatcher send_done_watcher; |
| 443 | 450 |
| 444 ReceivedSyncMsgQueue* sync_msg_queue = sync_context()->received_sync_msgs(); | 451 ReceivedSyncMsgQueue* sync_msg_queue = context->received_sync_msgs(); |
| 445 DCHECK(sync_msg_queue != NULL); | 452 DCHECK(sync_msg_queue != NULL); |
| 446 | 453 |
| 447 base::WaitableEventWatcher* old_send_done_event_watcher = | 454 base::WaitableEventWatcher* old_send_done_event_watcher = |
| 448 sync_msg_queue->top_send_done_watcher(); | 455 sync_msg_queue->top_send_done_watcher(); |
| 449 | 456 |
| 450 base::WaitableEventWatcher::Delegate* old_delegate = NULL; | 457 base::WaitableEventWatcher::Delegate* old_delegate = NULL; |
| 451 base::WaitableEvent* old_event = NULL; | 458 base::WaitableEvent* old_event = NULL; |
| 452 | 459 |
| 453 // Maintain a local global stack of send done delegates to ensure that | 460 // Maintain a local global stack of send done delegates to ensure that |
| 454 // nested sync calls complete in the correct sequence, i.e. the | 461 // nested sync calls complete in the correct sequence, i.e. the |
| 455 // outermost call completes first, etc. | 462 // outermost call completes first, etc. |
| 456 if (old_send_done_event_watcher) { | 463 if (old_send_done_event_watcher) { |
| 457 old_delegate = old_send_done_event_watcher->delegate(); | 464 old_delegate = old_send_done_event_watcher->delegate(); |
| 458 old_event = old_send_done_event_watcher->GetWatchedEvent(); | 465 old_event = old_send_done_event_watcher->GetWatchedEvent(); |
| 459 old_send_done_event_watcher->StopWatching(); | 466 old_send_done_event_watcher->StopWatching(); |
| 460 } | 467 } |
| 461 | 468 |
| 462 sync_msg_queue->set_top_send_done_watcher(&send_done_watcher); | 469 sync_msg_queue->set_top_send_done_watcher(&send_done_watcher); |
| 463 | 470 |
| 464 send_done_watcher.StartWatching(sync_context()->GetSendDoneEvent(), this); | 471 send_done_watcher.StartWatching(context->GetSendDoneEvent(), context); |
| 465 bool old_state = MessageLoop::current()->NestableTasksAllowed(); | 472 bool old_state = MessageLoop::current()->NestableTasksAllowed(); |
| 466 | 473 |
| 467 MessageLoop::current()->SetNestableTasksAllowed(true); | 474 MessageLoop::current()->SetNestableTasksAllowed(true); |
| 468 MessageLoop::current()->Run(); | 475 MessageLoop::current()->Run(); |
| 469 MessageLoop::current()->SetNestableTasksAllowed(old_state); | 476 MessageLoop::current()->SetNestableTasksAllowed(old_state); |
| 470 | 477 |
| 471 sync_msg_queue->set_top_send_done_watcher(old_send_done_event_watcher); | 478 sync_msg_queue->set_top_send_done_watcher(old_send_done_event_watcher); |
| 472 if (old_send_done_event_watcher && old_event) { | 479 if (old_send_done_event_watcher && old_event) { |
| 473 old_send_done_event_watcher->StartWatching(old_event, old_delegate); | 480 old_send_done_event_watcher->StartWatching(old_event, old_delegate); |
| 474 } | 481 } |
| 475 } | 482 } |
| 476 | 483 |
| 477 void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) { | 484 void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) { |
| 478 WaitableEvent* dispatch_event = sync_context()->GetDispatchEvent(); | 485 DCHECK(event == sync_context()->GetDispatchEvent()); |
| 479 if (event == dispatch_event) { | 486 // The call to DispatchMessages might delete this object, so reregister |
| 480 // The call to DispatchMessages might delete this object, so reregister | 487 // the object watcher first. |
| 481 // the object watcher first. | 488 event->Reset(); |
| 482 dispatch_event->Reset(); | 489 dispatch_watcher_.StartWatching(event, this); |
| 483 dispatch_watcher_.StartWatching(dispatch_event, this); | 490 sync_context()->DispatchMessages(); |
| 484 sync_context()->DispatchMessages(); | |
| 485 } else { | |
| 486 // We got the reply, timed out or the process shutdown. | |
| 487 DCHECK(event == sync_context()->GetSendDoneEvent()); | |
| 488 MessageLoop::current()->Quit(); | |
| 489 } | |
| 490 } | 491 } |
| 491 | 492 |
| 492 } // namespace IPC | 493 } // namespace IPC |
| OLD | NEW |