main: Add unhandled exception debug information

In general destructors should not throw exceptions because they are
possibly already being run during stack unwind from a previous
exception.  In those situations the process will terminate with no
opportunity for gracefully handling errors.

For the more typical case of primary exceptions during deconstruction,
the exceptions coming out of sendIntrospectionCompleteSignal are
unknown, so catch them, log them, and then terminate the process.  Over
time as the errors coming out of sendIntrospectionCompleteSignal are
discovered, those errors can be added to a set of expected errors that
need not terminate the process.

In the end, the behavior is only moderately changed - prior to this
patch this exception would already propagate and the application
terminate.  The new behavior here is simply to make a note that it
occurred, and to provide some guidance (this message) to whoever gets
the bug when sendIntrospectionCompleteSignal inevitably does fail and
throw an error.

Also, this makes clang happy (bugprone-exception-escape).

Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Change-Id: I67c11c732b3179afcf7174b6f09025083000b85b
diff --git a/src/main.cpp b/src/main.cpp
index c969777..65de2ad 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -15,6 +15,7 @@
 
 #include <atomic>
 #include <chrono>
+#include <exception>
 #include <iomanip>
 #include <iostream>
 #include <utility>
@@ -86,23 +87,38 @@
     {}
     ~InProgressIntrospect()
     {
-        sendIntrospectionCompleteSignal(systemBus, processName);
-
-#ifdef DEBUG
-        std::chrono::duration<float> diff =
-            std::chrono::steady_clock::now() - processStartTime;
-        std::cout << std::setw(50) << processName << " scan took "
-                  << diff.count() << " seconds\n";
-
-        // If we're the last outstanding caller globally, calculate the
-        // time it took
-        if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
+        try
         {
-            diff = std::chrono::steady_clock::now() - *globalStartTime;
-            std::cout << "Total scan took " << diff.count()
-                      << " seconds to complete\n";
-        }
+            sendIntrospectionCompleteSignal(systemBus, processName);
+#ifdef DEBUG
+            std::chrono::duration<float> diff =
+                std::chrono::steady_clock::now() - processStartTime;
+            std::cout << std::setw(50) << processName << " scan took "
+                      << diff.count() << " seconds\n";
+
+            // If we're the last outstanding caller globally, calculate the
+            // time it took
+            if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
+            {
+                diff = std::chrono::steady_clock::now() - *globalStartTime;
+                std::cout << "Total scan took " << diff.count()
+                          << " seconds to complete\n";
+            }
 #endif
+        }
+        catch (const std::exception& e)
+        {
+            std::cerr
+                << "Terminating, unhandled exception while introspecting: "
+                << e.what() << "\n";
+            std::terminate();
+        }
+        catch (...)
+        {
+            std::cerr
+                << "Terminating, unhandled exception while introspecting\n";
+            std::terminate();
+        }
     }
     sdbusplus::asio::connection* systemBus;
     boost::asio::io_context& io;