Cleanly error aos_starter when run before starterd

If fetching the status for an application before starterd had started
(and if doing so just for an individual application, rather than for
*all* applications), then aos_starter would segfault. Fail more
gracefully.

Change-Id: Ic4657d303403e116bc836dbf3803e43a533089b1
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/starter/starter_cmd.cc b/aos/starter/starter_cmd.cc
index ae65ff0..b3fb6c6 100644
--- a/aos/starter/starter_cmd.cc
+++ b/aos/starter/starter_cmd.cc
@@ -155,9 +155,20 @@
     }
     PrintKey();
     for (const aos::Node *node : application_nodes) {
-      auto status = aos::starter::GetStatus(application_name, config, node);
-      PrintApplicationStatus(&status.message(), aos::monotonic_clock::now(),
-                             node);
+      auto optional_status =
+          aos::starter::GetStatus(application_name, config, node);
+      if (optional_status.has_value()) {
+        PrintApplicationStatus(&optional_status.value().message(),
+                               aos::monotonic_clock::now(), node);
+      } else {
+        if (node != nullptr) {
+          LOG(ERROR) << "No status available yet for \"" << application_name
+                     << "\" on node \"" << node->name()->string_view() << "\".";
+        } else {
+          LOG(ERROR) << "No status available yet for \"" << application_name
+                     << "\".";
+        }
+      }
     }
   } else {
     LOG(ERROR) << "The \"status\" command requires zero or one arguments.";
diff --git a/aos/starter/starter_rpc_lib.cc b/aos/starter/starter_rpc_lib.cc
index 3007326..a5bdbdd 100644
--- a/aos/starter/starter_rpc_lib.cc
+++ b/aos/starter/starter_rpc_lib.cc
@@ -258,20 +258,23 @@
   return success;
 }
 
-const FlatbufferDetachedBuffer<aos::starter::ApplicationStatus> GetStatus(
-    std::string_view name, const Configuration *config, const aos::Node *node) {
+const std::optional<FlatbufferDetachedBuffer<aos::starter::ApplicationStatus>>
+GetStatus(std::string_view name, const Configuration *config,
+          const aos::Node *node) {
   ShmEventLoop event_loop(config);
   event_loop.SkipAosLog();
 
   auto status_fetcher = event_loop.MakeFetcher<aos::starter::Status>(
       StatusChannelForNode(config, node)->name()->string_view());
   status_fetcher.Fetch();
-  auto status = status_fetcher.get()
-                    ? FindApplicationStatus(*status_fetcher, name)
-                    : nullptr;
-  return status ? aos::CopyFlatBuffer(status)
-                : FlatbufferDetachedBuffer<
-                      aos::starter::ApplicationStatus>::Empty();
+  if (status_fetcher.get() != nullptr) {
+    const aos::starter::ApplicationStatus *status =
+        FindApplicationStatus(*status_fetcher, name);
+    if (status != nullptr) {
+      return aos::CopyFlatBuffer(status);
+    }
+  }
+  return std::nullopt;
 }
 
 std::optional<std::pair<aos::monotonic_clock::time_point,
diff --git a/aos/starter/starter_rpc_lib.h b/aos/starter/starter_rpc_lib.h
index 7b93e24..f91fb9e 100644
--- a/aos/starter/starter_rpc_lib.h
+++ b/aos/starter/starter_rpc_lib.h
@@ -97,11 +97,12 @@
                          std::chrono::milliseconds timeout);
 
 // Fetches the status of the application with the given name. Creates a
-// temporary event loop from the provided config for fetching. Returns an empty
-// flatbuffer if the application is not found.
-const aos::FlatbufferDetachedBuffer<aos::starter::ApplicationStatus> GetStatus(
-    std::string_view name, const aos::Configuration *config,
-    const aos::Node *node);
+// temporary event loop from the provided config for fetching. Returns nullopt
+// if the application is not found.
+const std::optional<
+    aos::FlatbufferDetachedBuffer<aos::starter::ApplicationStatus>>
+GetStatus(std::string_view name, const aos::Configuration *config,
+          const aos::Node *node);
 
 // Fetches the entire status message of starter. Creates a temporary event loop
 // from the provided config for fetching.