Fix memory leak on UpdateManager's event loop wrapper.

When an scheduled Closure is canceled, the memory associated with the
Closure object wasn't removed, leaking its memory. This patch deletes
the Closure in both cases: when it is executed and when it is
canceled.

BUG=chromium:378548
TEST=`FEATURES="test" USE="clang asan" emerge-link update_engine` doesn't complain about RunFromMainLoopAfterTimeout.

Change-Id: I10d8f58aaf0fb1fd746701a25f3ef0f8ccdf6c12
Reviewed-on: https://chromium-review.googlesource.com/202061
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/update_manager/event_loop.cc b/update_manager/event_loop.cc
index 6ae6d36..bc2940b 100644
--- a/update_manager/event_loop.cc
+++ b/update_manager/event_loop.cc
@@ -17,10 +17,13 @@
 gboolean OnRanFromMainLoop(gpointer user_data) {
   Closure* callback_p = reinterpret_cast<Closure*>(user_data);
   callback_p->Run();
-  delete callback_p;
   return FALSE;  // Removes the source since a callback can only be called once.
 }
 
+void DestroyClosure(gpointer user_data) {
+  delete reinterpret_cast<Closure*>(user_data);
+}
+
 }  // namespace
 
 namespace chromeos_update_manager {
@@ -30,16 +33,19 @@
   return g_idle_add_full(G_PRIORITY_DEFAULT,
                          OnRanFromMainLoop,
                          reinterpret_cast<gpointer>(callback_p),
-                         NULL);
+                         DestroyClosure);
 }
 
 EventId RunFromMainLoopAfterTimeout(
     const Closure& callback,
     base::TimeDelta timeout) {
   Closure* callback_p = new Closure(callback);
-  return g_timeout_add_seconds(static_cast<guint>(ceil(timeout.InSecondsF())),
-                               OnRanFromMainLoop,
-                               reinterpret_cast<gpointer>(callback_p));
+  return g_timeout_add_seconds_full(
+      G_PRIORITY_DEFAULT,
+      static_cast<guint>(ceil(timeout.InSecondsF())),
+      OnRanFromMainLoop,
+      reinterpret_cast<gpointer>(callback_p),
+      DestroyClosure);
 }
 
 bool CancelMainLoopEvent(EventId event) {