[sessionmgr] Fix sessionmgr crash that happens on agent runner teardown

- Sessionmgr crashes in debug builds when printing |message| because
it is corrupted in AgentRunner::Teardown

- Corruption happens because |termination_callback_| execution destroys
AgentRunner along with the captures (the |message|)

- This fix is an alternative to 246372, it avoids putting the termination
callback on heap.

MF-163 #done
MF-171 #done

TESTED: run_modular_tests
Change-Id: Iab2acc84679f1d5ddd1a0b924d9fb2a319c1aebe
diff --git a/bin/sessionmgr/agent_runner/agent_context_impl.cc b/bin/sessionmgr/agent_runner/agent_context_impl.cc
index 0ec1887..641b932 100644
--- a/bin/sessionmgr/agent_runner/agent_context_impl.cc
+++ b/bin/sessionmgr/agent_runner/agent_context_impl.cc
@@ -37,9 +37,8 @@
   InitializeCall(AgentContextImpl* const agent_context_impl,
                  fuchsia::sys::Launcher* const launcher,
                  fuchsia::modular::AppConfig agent_config)
-      : Operation(
-            "AgentContextImpl::InitializeCall", [] {},
-            agent_context_impl->url_),
+      : Operation("AgentContextImpl::InitializeCall", [] {},
+                  agent_context_impl->url_),
         agent_context_impl_(agent_context_impl),
         launcher_(launcher),
         agent_config_(std::move(agent_config)) {}
@@ -280,18 +279,17 @@
     fuchsia::auth::AppConfig app_config,
     fidl::InterfaceHandle<fuchsia::auth::AuthenticationUIContext>
         auth_ui_context,
-    std::vector<::std::string> app_scopes,
-    fidl::StringPtr user_profile_id, fidl::StringPtr auth_code,
-    AuthorizeCallback callback) {
+    std::vector<::std::string> app_scopes, fidl::StringPtr user_profile_id,
+    fidl::StringPtr auth_code, AuthorizeCallback callback) {
   FXL_LOG(ERROR) << "AgentContextImpl::Authorize() not supported from agent "
                  << "context";
   callback(fuchsia::auth::Status::INVALID_REQUEST, nullptr);
 }
 
-void AgentContextImpl::GetAccessToken(
-    fuchsia::auth::AppConfig app_config, std::string user_profile_id,
-    std::vector<::std::string> app_scopes,
-    GetAccessTokenCallback callback) {
+void AgentContextImpl::GetAccessToken(fuchsia::auth::AppConfig app_config,
+                                      std::string user_profile_id,
+                                      std::vector<::std::string> app_scopes,
+                                      GetAccessTokenCallback callback) {
   FXL_CHECK(token_manager_);
 
   FXL_DLOG(INFO) << "AgentContextImpl::GetAccessToken() invoked for user:"
@@ -353,12 +351,13 @@
                                     }));
 }
 
-void AgentContextImpl::StopForTeardown() {
+void AgentContextImpl::StopForTeardown(const std::function<void()>& callback) {
   FXL_DLOG(INFO) << "AgentContextImpl::StopForTeardown() " << url_;
   operation_queue_.Add(new StopCall(true /* is agent runner terminating? */,
-                                    this, [this](bool stopped) {
+                                    this, [this, callback](bool stopped) {
                                       FXL_DCHECK(stopped);
                                       agent_runner_->RemoveAgent(url_);
+                                      callback();
                                       // |this| is no longer valid at this
                                       // point.
                                     }));
diff --git a/bin/sessionmgr/agent_runner/agent_context_impl.h b/bin/sessionmgr/agent_runner/agent_context_impl.h
index be9c736..afb742c 100644
--- a/bin/sessionmgr/agent_runner/agent_context_impl.h
+++ b/bin/sessionmgr/agent_runner/agent_context_impl.h
@@ -49,7 +49,7 @@
   // Stops the running agent, irrespective of whether there are active
   // AgentControllers or outstanding tasks. Calls into
   // |AgentRunner::RemoveAgent()| to remove itself.
-  void StopForTeardown();
+  void StopForTeardown(const std::function<void()>& callback);
 
   // Called by AgentRunner when a component wants to connect to this agent.
   // Connections will pend until fuchsia::modular::Agent::Initialize() responds
diff --git a/bin/sessionmgr/agent_runner/agent_runner.cc b/bin/sessionmgr/agent_runner/agent_runner.cc
index ef38087..47cf6c2 100644
--- a/bin/sessionmgr/agent_runner/agent_runner.cc
+++ b/bin/sessionmgr/agent_runner/agent_runner.cc
@@ -65,7 +65,8 @@
 
   // This is called when agents are done being removed
   auto called = std::make_shared<bool>(false);
-  auto cont = [this, called, callback](const bool from_timeout) {
+  auto termination_callback = [this, called,
+                               callback](const bool from_timeout) {
     if (*called) {
       return;
     }
@@ -79,19 +80,22 @@
     callback();
   };
 
-  termination_callback_ = [cont] { cont(false); };
-
   for (auto& it : running_agents_) {
     // The running agent will call |AgentRunner::RemoveAgent()| to remove itself
     // from the agent runner. When all agents are done being removed,
-    // |RemoveAgent()| will call |termination_callback_|.
-    it.second->StopForTeardown();
+    // |termination_callback| will be executed.
+    it.second->StopForTeardown([this, termination_callback]() {
+      if (running_agents_.empty()) {
+        termination_callback(/* from_timeout= */ false);
+      }
+    });
   }
 
-  auto cont_timeout = [cont] { cont(true); };
-
   async::PostDelayedTask(async_get_default_dispatcher(),
-                         std::move(cont_timeout), kTeardownTimeout);
+                         [termination_callback] {
+                           termination_callback(/* from_timeout= */ true);
+                         },
+                         kTeardownTimeout);
 }
 
 void AgentRunner::EnsureAgentIsRunning(const std::string& agent_url,
@@ -188,9 +192,7 @@
 void AgentRunner::RemoveAgent(const std::string agent_url) {
   running_agents_.erase(agent_url);
 
-  if (*terminating_ && running_agents_.empty()) {
-    FXL_DCHECK(termination_callback_);
-    termination_callback_();
+  if (*terminating_) {
     return;
   }
 
diff --git a/bin/sessionmgr/agent_runner/agent_runner.h b/bin/sessionmgr/agent_runner/agent_runner.h
index 48ddf28..ca734f0 100644
--- a/bin/sessionmgr/agent_runner/agent_runner.h
+++ b/bin/sessionmgr/agent_runner/agent_runner.h
@@ -218,9 +218,6 @@
 
   // When this is marked true, no new new tasks will be scheduled.
   std::shared_ptr<bool> terminating_;
-  // This is called as part of the |StopForTeardown()| flow, when the last agent
-  // is torn down.
-  std::function<void()> termination_callback_;
 
   OperationQueue operation_queue_;