openbmc / sdbusplus

C++ bindings for systemd dbus APIs
Apache License 2.0
101 stars 80 forks source link

Need support for tuple message type #50

Closed manojkiraneda closed 3 years ago

manojkiraneda commented 3 years ago

I am not sure if this qualifies as a bug for sdbusplus or some other repo(bios-settings-mgr). I have been testing my code against https://gerrit.openbmc-project.xyz/c/openbmc/bios-settings-mgr/+/35563.

Here is my sample code :

#include <sdbusplus/bus.hpp>
#include <xyz/openbmc_project/BIOSConfig/Manager/server.hpp>
#include <cstdint>
#include <iostream>

int main()
{
    using namespace sdbusplus;

    auto b = bus::new_default_system();
    auto m =
        b.new_method_call("xyz.openbmc_project.BIOSConfigManager", "/xyz/openbmc_project/bios_config/manager",
                          "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute");
    m.append("vmi-hostname");
    auto reply = b.call(m);

std::tuple<xyz::openbmc_project::BIOSConfig::server::Manager::AttributeType,std::variant<int64_t,std::string>,std::variant<int64_t,std::string>> attributeMesg;
//    std::tuple<int64_t, std::variant<int64_t,std::string>, std::variant<int64_t,std::string>> attributeMesg;

    try
    {
        reply.read(attributeMesg);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
            std::cout<< "Failed to read the dbus message into provided container" << e.what();
    }
    return 0;
}

I get this error when executing the binary:

root@witherspoon:/tmp# ./test 
Failed to read the dbus message into provided containersd_bus_message_enter_container tuple: System.Error.ENXIO:

But i see the underlying busctl call succeded - using busctl monitor

‣ Type=method_return  Endian=l  Flags=1  Version=1 Cookie=26  ReplyCookie=2
  Sender=:1.100  Destination=:1.108
  UniqueName=:1.100
  MESSAGE "svv" {
          STRING "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String";
          VARIANT "s" {
                  STRING "witherspoon";
          };
          VARIANT "x" {
                  INT64 0;
          };
  };

And the busctl call also seems to return fine:

root@witherspoon:/tmp# busctl call xyz.openbmc_project.BIOSConfigManager /xyz/openbmc_project/bios_config/manager xyz.openbmc_project.BIOSConfig.Manager GetAttribute s "vmi-hostname"
svv "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String" s "witherspoon" x 0

The message signature is svv -> so i was using a tuple<string,variant,variant> container to catch the dbus message. Am i doing something wrong ? or is the sdbusplus lacking support for tuple message type ?

williamspatrick commented 3 years ago

Hi @manojkiraneda . The short answer is that you are calling reply.read(...) incorrectly.

Tuple is supported by sdbusplus, and this shows because the code compiled. What happens though is that we treat a C++ tuple type as equivalent to the dbus struct type. What you’re doing by passing the tuple directly to read is you are asking sdbusplus to pull a struct out of the message, which isn’t there, and hence the ENXIO error (from the underlying sdbus function we call).

You need to pass the elements of the tuple to the read independently.

reply.read(attr.get<0>(), attr.get<1>(), attr.get<2>());

Alternatively, if you don’t have need for a tuple otherwise, you can pass references to 3 local variables directly.