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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions