Change async_method_call to be no-throw

The async_method_call() would throw despite the inferred promise that it
would not, because the handler would be passed an error_code object. But
that would only protect from the dbus method call itself.  When it came
time to unpack the response, the read_into_tuple(...) method call would
throw if the received types did not match the expected types. And
because this throw would happen in a separate boost::asio context, the
throw would always be fatal. Now, any exception during the D-Bus call or
unpacking of parameters will result in an error_code getting passed into
the handler so it can take appropriate action.

This also updates the example to remove try/catch statements around the
async_method_call and yield_method_call examples and shows what happens
if the method calls fail because of different types of errors
(api/function does not exist vs. incorrect unpack types).

Tested-by: run asio-example to see that it works as expected:
    # /tmp/asio-example
    voidBar() -> 42
    fooYield(yield, 41)...
    async_send callback
    error with async_send
    ipmiInterface:execute(61)
    async_method_call callback
    /org/openbmc/control/bmc0
    /org/openbmc/control/flash/bmc
    fooYield(yield, 41)...
    ipmi call returns OK!
    foo(41) -> 42
    async_method_call callback
    async_method_call expected failure: generic:foo(41) -> 42
    yielding call to foo OK! (-> 42)
    22
    async call to Properties.Get serialized via yield OK!
    TestYieldFunction return 42
    yielding call to foo OK! (-> 42)
    yielding call to TestYieldFunction serialized via yield OK!
    fooYield(yield, 41)...
    foo(41) -> 42
    async call to Properties.Get serialized via yield OK!
    yielding call to foo OK! (-> 42)
    TestYieldFunction expected error: generic:22
    TestYieldFunctionNotExits expected error: generic:53
    *** tick ***
    *** tock ***
    *** tick ***
    *** tick ***
    *** tick ***

Change-Id: I53c91484ed496556342b3ed0a58b690872a2d676
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>

stuff

Change-Id: I48da27be7ba8c63f44c12a8b79fffb8f3e085648
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/example/asio-example.cpp b/example/asio-example.cpp
index 2cd1323..f04af3f 100644
--- a/example/asio-example.cpp
+++ b/example/asio-example.cpp
@@ -146,17 +146,10 @@
 {
     boost::system::error_code ec;
     int testValue = 0;
-    try
-    {
-        testValue = conn->yield_method_call<int>(
-            yield, ec, "xyz.openbmc_project.asio-test",
-            "/xyz/openbmc_project/test", "xyz.openbmc_project.test",
-            "TestYieldFunction", int(41));
-    }
-    catch (sdbusplus::exception::SdBusError& e)
-    {
-        std::cout << "oops: " << e.what() << "\n";
-    }
+    testValue = conn->yield_method_call<int>(
+        yield, ec, "xyz.openbmc_project.asio-test", "/xyz/openbmc_project/test",
+        "xyz.openbmc_project.test", "TestYieldFunction", int(41));
+
     if (!ec && testValue == 42)
     {
         std::cout
@@ -166,6 +159,35 @@
     {
         std::cout << "ec = " << ec << ": " << testValue << "\n";
     }
+
+    ec.clear();
+    auto badValue = conn->yield_method_call<std::string>(
+        yield, ec, "xyz.openbmc_project.asio-test", "/xyz/openbmc_project/test",
+        "xyz.openbmc_project.test", "TestYieldFunction", int(41));
+
+    if (!ec)
+    {
+        std::cout
+            << "yielding call to TestYieldFunction returned the wrong type\n";
+    }
+    else
+    {
+        std::cout << "TestYieldFunction expected error: " << ec << "\n";
+    }
+
+    ec.clear();
+    auto unUsedValue = conn->yield_method_call<std::string>(
+        yield, ec, "xyz.openbmc_project.asio-test", "/xyz/openbmc_project/test",
+        "xyz.openbmc_project.test", "TestYieldFunctionNotExits", int(41));
+
+    if (!ec)
+    {
+        std::cout << "TestYieldFunctionNotExists returned unexpectedly\n";
+    }
+    else
+    {
+        std::cout << "TestYieldFunctionNotExits expected error: " << ec << "\n";
+    }
 }
 
 int server()
@@ -317,6 +339,25 @@
         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
         "/org/openbmc/control", 2, std::vector<std::string>());
 
+    conn->async_method_call(
+        [](boost::system::error_code ec,
+           const std::vector<std::string>& things) {
+            std::cout << "async_method_call callback\n";
+            if (ec)
+            {
+                std::cerr << "async_method_call expected failure: " << ec
+                          << "\n";
+            }
+            else
+            {
+                std::cerr << "asyn_method_call should have faild!\n";
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+        "/xyz/openbmc_project/sensors", depth, interfaces);
+
     // sd_events work too using the default event loop
     phosphor::Timer t1([]() { std::cerr << "*** tock ***\n"; });
     t1.start(std::chrono::microseconds(1000000));
diff --git a/sdbusplus/asio/connection.hpp b/sdbusplus/asio/connection.hpp
index 9b570be..083bfdf 100644
--- a/sdbusplus/asio/connection.hpp
+++ b/sdbusplus/asio/connection.hpp
@@ -132,7 +132,11 @@
             UnpackType responseData;
             if (!ec)
             {
-                if (!utility::read_into_tuple(responseData, r))
+                try
+                {
+                    utility::read_into_tuple(responseData, r);
+                }
+                catch (const std::exception& e)
                 {
                     // Set error code if not already set
                     ec = boost::system::errc::make_error_code(