Index: mojo/public/cpp/bindings/lib/connector.cc |
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc |
index 7f9a9c30856e1a35fcc25b3e1d28d6007d02221b..812b4c1133f56db708729a82055cbb24e9671456 100644 |
--- a/mojo/public/cpp/bindings/lib/connector.cc |
+++ b/mojo/public/cpp/bindings/lib/connector.cc |
@@ -11,6 +11,7 @@ |
#include "base/logging.h" |
#include "base/macros.h" |
#include "base/synchronization/lock.h" |
+#include "base/thread_task_runner_handle.h" |
#include "mojo/public/cpp/bindings/lib/sync_handle_watcher.h" |
namespace mojo { |
@@ -247,7 +248,7 @@ bool Connector::RunSyncHandleWatch(const bool* should_stop) { |
return SyncHandleWatcher::current()->WatchAllHandles(should_stop_array, 2); |
} |
-void Connector::OnHandleWatcherHandleReady(MojoResult result) { |
+void Connector::OnWatcherHandleReady(MojoResult result) { |
OnHandleReadyInternal(result); |
} |
@@ -273,12 +274,21 @@ void Connector::OnHandleReadyInternal(MojoResult result) { |
} |
void Connector::WaitToReadMore() { |
- CHECK(!handle_watcher_.is_watching()); |
CHECK(!paused_); |
- handle_watcher_.Start(message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, |
- MOJO_DEADLINE_INDEFINITE, |
- base::Bind(&Connector::OnHandleWatcherHandleReady, |
- base::Unretained(this))); |
+ DCHECK(!handle_watcher_.IsWatching()); |
+ |
+ MojoResult rv = handle_watcher_.Start( |
+ message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, |
+ base::Bind(&Connector::OnWatcherHandleReady, |
+ base::Unretained(this))); |
+ |
+ if (rv != MOJO_RESULT_OK) { |
+ // If the watch failed because the handle is invalid or its conditions can |
+ // no longer be met, we signal the error asynchronously to avoid reentry. |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&Connector::OnWatcherHandleReady, |
+ weak_factory_.GetWeakPtr(), rv)); |
+ } |
if (register_sync_handle_watch_count_ > 0 && |
!registered_with_sync_handle_watcher_) { |
@@ -304,13 +314,6 @@ bool Connector::ReadSingleMessage(MojoResult* read_result) { |
*read_result = rv; |
if (rv == MOJO_RESULT_OK) { |
- // Dispatching the message may spin in a nested message loop. To ensure we |
- // continue dispatching messages when this happens start listening for |
- // messagse now. |
- if (!handle_watcher_.is_watching()) { |
- // TODO: Need to evaluate the perf impact of this. |
- WaitToReadMore(); |
- } |
receiver_result = |
incoming_receiver_ && incoming_receiver_->Accept(&message); |
} |
@@ -344,21 +347,13 @@ void Connector::ReadAllAvailableMessages() { |
if (paused_) |
return; |
- if (rv == MOJO_RESULT_SHOULD_WAIT) { |
- // ReadSingleMessage could end up calling HandleError which resets |
- // message_pipe_ to a dummy one that is closed. The old EDK will see the |
- // that the peer is closed immediately, while the new one is asynchronous |
- // because of thread hops. In that case, there'll still be an async |
- // waiter. |
- if (!handle_watcher_.is_watching()) |
- WaitToReadMore(); |
+ if (rv == MOJO_RESULT_SHOULD_WAIT) |
break; |
- } |
} |
} |
void Connector::CancelWait() { |
- handle_watcher_.Stop(); |
+ handle_watcher_.Cancel(); |
if (registered_with_sync_handle_watcher_) { |
SyncHandleWatcher::current()->UnregisterHandle(message_pipe_.get()); |
@@ -394,8 +389,6 @@ void Connector::HandleError(bool force_pipe_reset, bool force_async_handler) { |
} |
if (force_async_handler) { |
- // |dummy_pipe.handle1| has been destructed. Reading the pipe will |
- // eventually cause a read error on |message_pipe_| and set error state. |
if (!paused_) |
WaitToReadMore(); |
} else { |