Skip to content

yield_method_call_timed overwrites real error code with invalid_argument when async_send fails #115

Description

@ClaudiusJXK

Summary

In connection.hpp, yield_method_call unconditionally calls
message_t::unpack() on the reply even when the underlying async_send
failed. Since unpack() will throw on a non-success / error reply, the
catch (...) block replaces the original (meaningful) error code with
boost::system::errc::invalid_argument, masking the real failure cause.

Location

File: include/sdbusplus/asio/connection.hpp
Function: yield_method_call
Lines (approx): 276-289

        if (!ec)
        {
            message_t r;
            r = async_send_yield(m, yield[ec]);
            try
            {
                return r.unpack<RetTypes...>();
            }
            catch (const std::exception&)
            {
                ec = boost::system::errc::make_error_code(
                    boost::system::errc::invalid_argument);
            }
        }

When async_send fails (e.g. D-Bus method error, timeout, connection error), the returned message_t r is either the original request message (synchronous failure path in async_send_handler::operator(), where the handler is invoked with mesg) or a METHOD_ERROR reply. Neither can be unpacked into RetTypes..., so unpack() throws, the catch (...) block runs, and ec is overwritten with invalid_argument.

As a result the caller cannot distinguish between:

a transport / D-Bus level failure (timeout, ENOENT, ETIMEDOUT, method error, ...), and
an actual return-value deserialization failure.
All real error diagnostics are lost, which makes diagnosing issues in the field very difficult.

Suggested fix

        if (!ec)
        {
            message_t r;
            r = async_send_yield(m, yield[ec]);

            if (!ec)
            {
               try
               {
                   return r.unpack<RetTypes...>();
               }
               catch (const std::exception&)
               {
                  ec = boost::system::errc::make_error_code(
                    boost::system::errc::invalid_argument);
                }
            }
        }

This brings the behavior in line with async_method_call_timed and preserves the real error code on transport / D-Bus level failures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions