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