UM: Fix async callback handling.
A bug in EvaluationContext::OnValueChangedOrPollTimeout() causes
scheduling of a reevaluation to fail. We fix it by copying the callback
pointer to a local variable and clearing it prior to invoking the
callback.
This also adds a check in the evaluation context unit tests code to
ensure that the EC under test is actually being destroyed; this is
useful to ensure that unit tests are not leaking EC references, e.g. by
form of pending main loop events that are holding EC handles in
closures.
BUG=chromium:391037
TEST=New unit test fails before fix, succeeds after it.
Change-Id: I63486b80525ec19d0cd399c52eea39d991a4ff53
Reviewed-on: https://chromium-review.googlesource.com/206538
Tested-by: Gilad Arnold <[email protected]>
Reviewed-by: Alex Deymo <[email protected]>
Commit-Queue: Gilad Arnold <[email protected]>
diff --git a/update_manager/evaluation_context.cc b/update_manager/evaluation_context.cc
index a24bf23..da69ced 100644
--- a/update_manager/evaluation_context.cc
+++ b/update_manager/evaluation_context.cc
@@ -59,10 +59,10 @@
void EvaluationContext::OnValueChangedOrPollTimeout() {
RemoveObserversAndTimeout();
- if (value_changed_callback_.get() != NULL) {
- value_changed_callback_->Run();
- value_changed_callback_.reset();
- }
+ // Copy the callback handle locally, allowing the callback code to reset it.
+ scoped_ptr<Closure> callback(value_changed_callback_.release());
+ if (callback.get() != NULL)
+ callback->Run();
}
bool EvaluationContext::IsTimeGreaterThan(base::Time timestamp) {
@@ -133,6 +133,9 @@
if (!waiting_for_value_change && !reeval_timeout_set)
return false;
if (reeval_timeout_set) {
+ DLOG(INFO)
+ << "Waiting for poll timeout in "
+ << chromeos_update_engine::utils::FormatTimeDelta(reeval_timeout);
poll_timeout_event_ = RunFromMainLoopAfterTimeout(
base::Bind(&EvaluationContext::OnPollTimeout,
weak_ptr_factory_.GetWeakPtr()),