CleanupPreviousUpdateAction: cancel pending tasks on destroy

Maintain a variable that tracks the task ID of the pending
task in the message loop. On destroy, cancel the pending
task to avoid segfault.

Test: during merge, call update_engine_client --cancel and
      it does not crash
Fixes: 169436297
Change-Id: I9f3bccc5d4d5e2aaad1d08ef815c50100220c870
diff --git a/cleanup_previous_update_action.h b/cleanup_previous_update_action.h
index 1d8d3d7..fe65e60 100644
--- a/cleanup_previous_update_action.h
+++ b/cleanup_previous_update_action.h
@@ -20,6 +20,7 @@
 #include <chrono>  // NOLINT(build/c++11) -- for merge times
 #include <memory>
 #include <string>
+#include <string_view>
 
 #include <brillo/message_loops/message_loop.h>
 #include <libsnapshot/snapshot.h>
@@ -51,6 +52,7 @@
       BootControlInterface* boot_control,
       android::snapshot::ISnapshotManager* snapshot,
       CleanupPreviousUpdateActionDelegateInterface* delegate);
+  ~CleanupPreviousUpdateAction();
 
   void PerformAction() override;
   void SuspendAction() override;
@@ -74,6 +76,11 @@
   bool cancel_failed_{false};
   unsigned int last_percentage_{0};
   android::snapshot::ISnapshotMergeStats* merge_stats_;
+  brillo::MessageLoop::TaskId scheduled_task_{brillo::MessageLoop::kTaskIdNull};
+
+  // Helpers for task management.
+  void AcknowledgeTaskExecuted();
+  void CheckTaskScheduled(std::string_view name);
 
   void StopActionInternal();
   void StartActionInternal();