Index: mojo/system/raw_channel_win.cc |
diff --git a/mojo/system/raw_channel_win.cc b/mojo/system/raw_channel_win.cc |
index f772287c9b98fdc2db30c39cb945afbe571043e2..8568e8e7317e3a000784d7b48173b2e44cc5a76b 100644 |
--- a/mojo/system/raw_channel_win.cc |
+++ b/mojo/system/raw_channel_win.cc |
@@ -6,12 +6,13 @@ |
#include <windows.h> |
-#include "base/basictypes.h" |
+#include "base/auto_reset.h" |
#include "base/bind.h" |
#include "base/compiler_specific.h" |
#include "base/lazy_instance.h" |
#include "base/location.h" |
#include "base/logging.h" |
+#include "base/macros.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop/message_loop.h" |
#include "base/synchronization/lock.h" |
@@ -124,11 +125,11 @@ class RawChannelWin : public RawChannel { |
// Must be called on the I/O thread. |
bool ShouldSelfDestruct() const; |
- // Must be called on the I/O thread. It could be called before or after |
- // detached from the owner. |
+ // Must be called on the I/O thread. It may be called before or after |
+ // detaching from the owner. |
void OnReadCompleted(DWORD bytes_read, DWORD error); |
- // Must be called on the I/O thread. It could be called before or after |
- // detached from the owner. |
+ // Must be called on the I/O thread. It may be called before or after |
+ // detaching from the owner. |
void OnWriteCompleted(DWORD bytes_written, DWORD error); |
embedder::ScopedPlatformHandle handle_; |
@@ -141,6 +142,7 @@ class RawChannelWin : public RawChannel { |
// The following members must be used on the I/O thread. |
scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_; |
scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_; |
+ bool suppress_self_destruct_; |
bool pending_read_; |
base::MessageLoopForIO::IOContext read_context_; |
@@ -178,6 +180,7 @@ RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( |
RawChannelWin* owner, |
embedder::ScopedPlatformHandle handle) : handle_(handle.Pass()), |
owner_(owner), |
+ suppress_self_destruct_(false), |
pending_read_(false), |
pending_write_(false) { |
memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); |
@@ -239,12 +242,18 @@ void RawChannelWin::RawChannelIOHandler::OnIOCompleted( |
DCHECK(!owner_ || |
base::MessageLoop::current() == owner_->message_loop_for_io()); |
- if (context == &read_context_) |
- OnReadCompleted(bytes_transferred, error); |
- else if (context == &write_context_) |
- OnWriteCompleted(bytes_transferred, error); |
- else |
- NOTREACHED(); |
+ { |
+ // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they |
+ // result in a call to |Shutdown()|). |
+ base::AutoReset<bool> resetter(&suppress_self_destruct_, true); |
+ |
+ if (context == &read_context_) |
+ OnReadCompleted(bytes_transferred, error); |
+ else if (context == &write_context_) |
+ OnWriteCompleted(bytes_transferred, error); |
+ else |
+ NOTREACHED(); |
+ } |
if (ShouldSelfDestruct()) |
delete this; |
@@ -269,7 +278,7 @@ void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( |
} |
bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { |
- if (owner_) |
+ if (owner_ || suppress_self_destruct_) |
return false; |
// Note: Detached, hence no lock needed for |pending_write_|. |
@@ -280,6 +289,7 @@ void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, |
DWORD error) { |
DCHECK(!owner_ || |
base::MessageLoop::current() == owner_->message_loop_for_io()); |
+ DCHECK(suppress_self_destruct_); |
CHECK(pending_read_); |
pending_read_ = false; |
@@ -300,6 +310,7 @@ void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, |
DWORD error) { |
DCHECK(!owner_ || |
base::MessageLoop::current() == owner_->message_loop_for_io()); |
+ DCHECK(suppress_self_destruct_); |
if (!owner_) { |
// No lock needed. |