Index: mojo/edk/system/raw_channel.cc |
diff --git a/mojo/edk/system/raw_channel.cc b/mojo/edk/system/raw_channel.cc |
index 819762b301641ba7dba8030d134da1ae2abbaa38..69a694bcffbb076a5760740168f87dad3117f093 100644 |
--- a/mojo/edk/system/raw_channel.cc |
+++ b/mojo/edk/system/raw_channel.cc |
@@ -170,6 +170,7 @@ RawChannel::RawChannel() |
write_ready_(false), |
write_stopped_(false), |
error_occurred_(false), |
+ pending_error_(false), |
weak_ptr_factory_(this) { |
read_buffer_.reset(new ReadBuffer); |
write_buffer_.reset(new WriteBuffer()); |
@@ -225,7 +226,7 @@ void RawChannel::Init(Delegate* delegate) { |
// This will notify the delegate about the read failure. Although we're on |
// the I/O thread, don't call it in the nested context. |
message_loop_for_io_->PostTask( |
- FROM_HERE, base::Bind(&RawChannel::OnReadCompleted, |
+ FROM_HERE, base::Bind(&RawChannel::CallOnReadCompleted, |
weak_ptr_factory_.GetWeakPtr(), io_result, 0)); |
} |
// Note: |ScheduleRead()| failure is treated as a read failure (by notifying |
@@ -330,11 +331,12 @@ bool RawChannel::SendQueuedMessagesNoLock() { |
if (io_result == IO_PENDING) |
return true; |
- bool result = OnWriteCompletedNoLock(io_result, platform_handles_written, |
- bytes_written); |
+ bool result = OnWriteCompletedInternalNoLock( |
+ io_result, platform_handles_written, bytes_written); |
if (!result) { |
// Even if we're on the I/O thread, don't call |OnError()| in the nested |
// context. |
+ pending_error_ = true; |
message_loop_for_io_->PostTask( |
FROM_HERE, |
base::Bind(&RawChannel::LockAndCallOnError, |
@@ -376,11 +378,9 @@ void RawChannel::SetSerializedData( |
} |
} |
-void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { |
+void RawChannel::OnReadCompletedNoLock(IOResult io_result, size_t bytes_read) { |
DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); |
- |
- base::AutoLock locker(read_lock_); |
- |
+ read_lock_.AssertAcquired(); |
// Keep reading data in a loop, and dispatch messages if enough data is |
// received. Exit the loop if any of the following happens: |
// - one or more messages were dispatched; |
@@ -437,23 +437,17 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { |
} while (io_result != IO_PENDING); |
} |
-void RawChannel::OnWriteCompleted(IOResult io_result, |
- size_t platform_handles_written, |
- size_t bytes_written) { |
+void RawChannel::OnWriteCompletedNoLock(IOResult io_result, |
+ size_t platform_handles_written, |
+ size_t bytes_written) { |
DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); |
+ write_lock_.AssertAcquired(); |
DCHECK_NE(io_result, IO_PENDING); |
- bool did_fail = false; |
- { |
- base::AutoLock locker(write_lock_); |
- did_fail = !OnWriteCompletedNoLock(io_result, platform_handles_written, |
- bytes_written); |
- } |
- |
- if (did_fail) { |
+ bool did_fail = !OnWriteCompletedInternalNoLock( |
+ io_result, platform_handles_written, bytes_written); |
+ if (did_fail) |
LockAndCallOnError(Delegate::ERROR_WRITE); |
- return; // |this| may have been destroyed in |CallOnError()|. |
- } |
} |
void RawChannel::SerializeReadBuffer(size_t additional_bytes_read, |
@@ -465,9 +459,9 @@ void RawChannel::SerializeReadBuffer(size_t additional_bytes_read, |
} |
void RawChannel::SerializeWriteBuffer( |
- std::vector<char>* buffer, |
size_t additional_bytes_written, |
- size_t additional_platform_handles_written) { |
+ size_t additional_platform_handles_written, |
+ std::vector<char>* buffer) { |
if (write_buffer_->IsEmpty()) { |
DCHECK_EQ(0u, additional_bytes_written); |
DCHECK_EQ(0u, additional_platform_handles_written); |
@@ -497,6 +491,7 @@ void RawChannel::EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message) { |
bool RawChannel::OnReadMessageForRawChannel( |
const MessageInTransit::View& message_view) { |
if (message_view.type() == MessageInTransit::Type::RAW_CHANNEL_QUIT) { |
+ pending_error_ = true; |
message_loop_for_io_->PostTask( |
FROM_HERE, base::Bind(&RawChannel::LockAndCallOnError, |
weak_ptr_factory_.GetWeakPtr(), |
@@ -547,9 +542,9 @@ void RawChannel::LockAndCallOnError(Delegate::Error error) { |
CallOnError(error); |
} |
-bool RawChannel::OnWriteCompletedNoLock(IOResult io_result, |
- size_t platform_handles_written, |
- size_t bytes_written) { |
+bool RawChannel::OnWriteCompletedInternalNoLock(IOResult io_result, |
+ size_t platform_handles_written, |
+ size_t bytes_written) { |
write_lock_.AssertAcquired(); |
DCHECK(!write_buffer_->message_queue_.IsEmpty()); |
@@ -680,5 +675,10 @@ void RawChannel::UpdateWriteBuffer(size_t platform_handles_written, |
} |
} |
+void RawChannel::CallOnReadCompleted(IOResult io_result, size_t bytes_read) { |
+ base::AutoLock locker(read_lock()); |
+ OnReadCompletedNoLock(io_result, bytes_read); |
+} |
+ |
} // namespace edk |
} // namespace mojo |