Index: mojo/common/message_pump_mojo.cc |
diff --git a/mojo/common/message_pump_mojo.cc b/mojo/common/message_pump_mojo.cc |
index c7903f2831be0bf5666ee3e7c1488b23ab2716b9..a2275925876143315fa45f61d0b98c7fbe0fbbfc 100644 |
--- a/mojo/common/message_pump_mojo.cc |
+++ b/mojo/common/message_pump_mojo.cc |
@@ -15,6 +15,20 @@ |
namespace mojo { |
namespace common { |
+namespace { |
+ |
+MojoDeadline TimeTicksToMojoDeadline(base::TimeTicks time_ticks, |
+ base::TimeTicks now) { |
+ // The is_null() check matches that of HandleWatcher as well as how |
+ // |delayed_work_time| is used. |
+ if (time_ticks.is_null()) |
+ return MOJO_DEADLINE_INDEFINITE; |
+ const int64_t delta = (time_ticks - now).InMicroseconds(); |
+ return delta < 0 ? static_cast<MojoDeadline>(0) : |
+ static_cast<MojoDeadline>(delta); |
+} |
+ |
+} // namespace |
// State needed for one iteration of WaitMany. The first handle and flags |
// corresponds to that of the control pipe. |
@@ -52,10 +66,10 @@ void MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler, |
const Handle& handle, |
MojoHandleSignals wait_signals, |
base::TimeTicks deadline) { |
- DCHECK(handler); |
+ CHECK(handler); |
DCHECK(handle.is_valid()); |
// Assume it's an error if someone tries to reregister an existing handle. |
- DCHECK_EQ(0u, handlers_.count(handle)); |
+ CHECK_EQ(0u, handlers_.count(handle)); |
Handler handler_data; |
handler_data.handler = handler; |
handler_data.wait_signals = wait_signals; |
@@ -104,7 +118,6 @@ void MessagePumpMojo::ScheduleDelayedWork( |
if (!run_state_) |
return; |
run_state_->delayed_work_time = delayed_work_time; |
- SignalControlPipe(*run_state_); |
} |
void MessagePumpMojo::DoRunLoop(RunState* run_state, Delegate* delegate) { |
@@ -186,7 +199,7 @@ void MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { |
void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) { |
// TODO(sky): deal with control pipe going bad. |
- for (size_t i = 1; i < wait_state.handles.size(); ++i) { |
+ for (size_t i = 0; i < wait_state.handles.size(); ++i) { |
const MojoResult result = |
Wait(wait_state.handles[i], wait_state.wait_signals[i], 0); |
if (result == MOJO_RESULT_INVALID_ARGUMENT) { |
@@ -196,9 +209,11 @@ void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) { |
CHECK(false); |
} else if (result == MOJO_RESULT_FAILED_PRECONDITION || |
result == MOJO_RESULT_CANCELLED) { |
+ CHECK_NE(i, 0u); // Indicates the control pipe went bad. |
+ |
// Remove the handle first, this way if OnHandleError() tries to remove |
// the handle our iterator isn't invalidated. |
- DCHECK(handlers_.find(wait_state.handles[i]) != handlers_.end()); |
+ CHECK(handlers_.find(wait_state.handles[i]) != handlers_.end()); |
MessagePumpMojoHandler* handler = |
handlers_[wait_state.handles[i]].handler; |
handlers_.erase(wait_state.handles[i]); |
@@ -209,9 +224,12 @@ void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) { |
} |
void MessagePumpMojo::SignalControlPipe(const RunState& run_state) { |
- // TODO(sky): deal with error? |
- WriteMessageRaw(run_state.write_handle.get(), NULL, 0, NULL, 0, |
- MOJO_WRITE_MESSAGE_FLAG_NONE); |
+ const MojoResult result = |
+ WriteMessageRaw(run_state.write_handle.get(), NULL, 0, NULL, 0, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE); |
+ // If we can't write we likely won't wake up the thread and there is a strong |
+ // chance we'll deadlock. |
+ CHECK_EQ(MOJO_RESULT_OK, result); |
} |
MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState( |
@@ -230,16 +248,15 @@ MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState( |
MojoDeadline MessagePumpMojo::GetDeadlineForWait( |
const RunState& run_state) const { |
- base::TimeTicks min_time = run_state.delayed_work_time; |
+ const base::TimeTicks now(internal::NowTicks()); |
+ MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, |
+ now); |
for (HandleToHandler::const_iterator i = handlers_.begin(); |
i != handlers_.end(); ++i) { |
- if (min_time.is_null() && i->second.deadline < min_time) |
- min_time = i->second.deadline; |
+ deadline = std::min( |
+ TimeTicksToMojoDeadline(i->second.deadline, now), deadline); |
} |
- return min_time.is_null() ? MOJO_DEADLINE_INDEFINITE : |
- std::max(static_cast<MojoDeadline>(0), |
- static_cast<MojoDeadline>( |
- (min_time - internal::NowTicks()).InMicroseconds())); |
+ return deadline; |
} |
} // namespace common |