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

Side by Side Diff: ipc/ipc_sync_channel.cc

Issue 455011: Don't use any member variables when sending a sync call... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years 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 | « ipc/ipc_sync_channel.h ('k') | ipc/ipc_sync_channel_unittest.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) 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
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
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
OLDNEW
« no previous file with comments | « ipc/ipc_sync_channel.h ('k') | ipc/ipc_sync_channel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698