Catch async errors so they do not throw

When running an async operation, it is not a good idea to throw because
the current running context is not the context that it was originally
registered from, it is the io run-loop context. So any methods that
*would* throw, must run in a try/catch and then set the error code
properly so that the handler will be notified of the error.

This was caught when a process (bmcweb) was used to invoke a call that
had a bad path. That was not caught and it caused bmcweb to abort
because of an unhandled exception.

Change-Id: Ie66a029066a3f463759089b44368b7518d0de8ce
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/sdbusplus/asio/connection.hpp b/sdbusplus/asio/connection.hpp
index 8dbd568..796d05a 100644
--- a/sdbusplus/asio/connection.hpp
+++ b/sdbusplus/asio/connection.hpp
@@ -120,28 +120,24 @@
                            const std::string& interf, const std::string& method,
                            const InputArgs&... a)
     {
-        message::message m = new_method_call(service.c_str(), objpath.c_str(),
-                                             interf.c_str(), method.c_str());
-        m.append(a...);
-        async_send(m, [handler = std::forward<MessageHandler>(handler)](
-                          boost::system::error_code ec,
-                          message::message& r) mutable {
-            using FunctionTuple =
-                boost::callable_traits::args_t<MessageHandler>;
-            using FunctionTupleType =
-                typename utility::decay_tuple<FunctionTuple>::type;
-            constexpr bool returnWithMsg = []() {
-                if constexpr (std::tuple_size_v<FunctionTupleType>> 1)
-                {
-                    return std::is_same_v<
-                        std::tuple_element_t<1, FunctionTupleType>,
-                        sdbusplus::message::message>;
-                }
-                return false;
-            }();
-            using UnpackType =
-                typename utility::strip_first_n_args<returnWithMsg ? 2 : 1,
-                                                     FunctionTupleType>::type;
+        using FunctionTuple = boost::callable_traits::args_t<MessageHandler>;
+        using FunctionTupleType =
+            typename utility::decay_tuple<FunctionTuple>::type;
+        constexpr bool returnWithMsg = []() {
+            if constexpr (std::tuple_size_v<FunctionTupleType>> 1)
+            {
+                return std::is_same_v<
+                    std::tuple_element_t<1, FunctionTupleType>,
+                    sdbusplus::message::message>;
+            }
+            return false;
+        }();
+        using UnpackType =
+            typename utility::strip_first_n_args<returnWithMsg ? 2 : 1,
+                                                 FunctionTupleType>::type;
+        auto applyHandler = [handler = std::forward<MessageHandler>(handler)](
+                                boost::system::error_code ec,
+                                message::message& r) mutable {
             UnpackType responseData;
             if (!ec)
             {
@@ -171,7 +167,23 @@
                                                std::move(responseData));
                 std::apply(handler, response);
             }
-        });
+        };
+        message::message m;
+        boost::system::error_code ec;
+        try
+        {
+            m = new_method_call(service.c_str(), objpath.c_str(),
+                                interf.c_str(), method.c_str());
+            m.append(a...);
+        }
+        catch (const exception::SdBusError& e)
+        {
+            ec = boost::system::errc::make_error_code(
+                static_cast<boost::system::errc::errc_t>(e.get_errno()));
+            applyHandler(ec, m);
+            return;
+        }
+        async_send(m, std::forward<decltype(applyHandler)>(applyHandler));
     }
 
     /** @brief Perform a yielding asynchronous method call, with input
@@ -195,10 +207,23 @@
                            const std::string& interf, const std::string& method,
                            const InputArgs&... a)
     {
-        message::message m = new_method_call(service.c_str(), objpath.c_str(),
-                                             interf.c_str(), method.c_str());
-        m.append(a...);
-        message::message r = async_send(m, yield[ec]);
+        message::message m;
+        try
+        {
+            m = new_method_call(service.c_str(), objpath.c_str(),
+                                interf.c_str(), method.c_str());
+            m.append(a...);
+        }
+        catch (const exception::SdBusError& e)
+        {
+            ec = boost::system::errc::make_error_code(
+                static_cast<boost::system::errc::errc_t>(e.get_errno()));
+        }
+        message::message r;
+        if (!ec)
+        {
+            r = async_send(m, yield[ec]);
+        }
         if constexpr (sizeof...(RetTypes) == 0)
         {
             // void return