Skip to content

Timeout error when GetManagedObjects called on my service #499

@abroekhof

Description

@abroekhof

Describe the bug
I'm trying to implement the BLE AdvertisementMonitor, and am getting a timeout when I call RegisterMonitor on org.bluez. It appears to be triggering a reverse GetManagedObjects on my service, which I thought would be handled by the Object Manager I created, but no luck.

To Reproduce
Here's the smallest reproducible version I could get. I can attach the glue files below if that would be helpful, but they were generated from the xml, so I don't expect the problem is there.

#include <signal.h>

#include <iostream>
#include <thread>

#include "adaptor/AdvertisementMonitor1_adaptor.h"
#include "proxy/AdvertisementMonitorManager1_proxy.h"

class ApplicationObjectManager
    : public sdbus::AdaptorInterfaces<sdbus::ObjectManager_adaptor> {
 public:
  ApplicationObjectManager(sdbus::IConnection& connection,
                           sdbus::ObjectPath objectPath)
      : AdaptorInterfaces(connection, std::move(objectPath)) {
    registerAdaptor();
  }

  ~ApplicationObjectManager() { unregisterAdaptor(); }
};

class AdvertisementMonitor
    : public sdbus::AdaptorInterfaces<org::bluez::AdvertisementMonitor1_adaptor,
                                      sdbus::ManagedObject_adaptor,
                                      sdbus::Properties_adaptor> {
 public:
  AdvertisementMonitor(sdbus::IConnection& connection,
                       sdbus::ObjectPath objectPath)
      : AdaptorInterfaces(connection, std::move(objectPath)) {
    registerAdaptor();
    emitInterfacesAddedSignal({sdbus::InterfaceName{
        org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME}});
  }

  ~AdvertisementMonitor() {
    emitInterfacesRemovedSignal({sdbus::InterfaceName{
        org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME}});
    unregisterAdaptor();
  }

 public:
  void Release() override {}
  void Activate() override {}
  void DeviceFound(const sdbus::ObjectPath& device) override {}
  void DeviceLost(const sdbus::ObjectPath& device) override {}

 protected:
  int16_t RSSILowThreshold() override { return 127; }
  int16_t RSSIHighThreshold() override { return 127; }
  uint16_t RSSILowTimeout() override { return 0; }
  uint16_t RSSIHighTimeout() override { return 0; }
  uint16_t RSSISamplingPeriod() override { return 0; }

  std::string Type() override { return "or_patterns"; }
  std::vector<sdbus::Struct<uint8_t, uint8_t, std::vector<uint8_t>>> Patterns()
      override {
    return {{0, 0xFF, {0x4c}}};
  }
};

class AdvertisementMonitorManager
    : public sdbus::ProxyInterfaces<
          org::bluez::AdvertisementMonitorManager1_proxy> {
 public:
  AdvertisementMonitorManager(sdbus::IConnection& connection,
                              sdbus::ServiceName destination,
                              sdbus::ObjectPath objectPath)
      : ProxyInterfaces{connection, std::move(destination),
                        std::move(objectPath)} {
    registerProxy();
  }

  ~AdvertisementMonitorManager() { unregisterProxy(); }
};

constexpr const char* BLUEZ_SERVICE = "org.bluez";
constexpr const char* DEVICE0 = "/org/bluez/hci0";

static std::atomic<bool> running{true};

static void sig_callback(int signum) {
  std::cout << "Signal received, shutting down..." << std::endl;
  running = false;
}

int main(int argc, char* argv[]) {
  if (signal(SIGINT, sig_callback) == SIG_ERR) {
    exit(-1);
  }

  auto connection = sdbus::createSystemBusConnection();
  connection->enterEventLoopAsync();

  auto application_object_manager = std::make_unique<ApplicationObjectManager>(
      *connection, sdbus::ObjectPath{"/org/example"});

  auto advertisement_monitor_manager =
      std::make_unique<AdvertisementMonitorManager>(
          *connection, sdbus::ServiceName{"org.bluez"},
          sdbus::ObjectPath{"/org/bluez/hci0"});

  advertisement_monitor_manager->RegisterMonitor(
      sdbus::ObjectPath{"/org/example/monitor"});

  std::cout << "Advertisement monitor registered. Press Ctrl+C to exit."
            << std::endl;

  while (running) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  connection->leaveEventLoop();

  return 0;
}

Expected behavior
I expect RegisterMonitor to return normally.

Real (buggy) behavior
Here are logs from dbus-monitor:

// Register Monitor is called.
method call time=1750287421.989479 sender=:1.230 -> destination=org.bluez serial=2 path=/org/bluez/hci0; interface=org.bluez.AdvertisementMonitorManager1; member=RegisterMonitor
   object path "/org/example/monitor"
method call time=1750287421.989673 sender=:1.166 -> destination=org.freedesktop.DBus serial=296 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0=':1.230'"
method return time=1750287421.989686 sender=org.freedesktop.DBus -> destination=:1.166 serial=176 reply_serial=296
method call time=1750287421.989857 sender=:1.166 -> destination=org.freedesktop.DBus serial=297 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetNameOwner
   string ":1.230"
method return time=1750287421.989867 sender=org.freedesktop.DBus -> destination=:1.166 serial=177 reply_serial=297
   string ":1.230"
method call time=1750287421.989921 sender=:1.166 -> destination=org.freedesktop.DBus serial=298 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender=':1.230',path='/org/example/monitor',interface='org.freedesktop.DBus.ObjectManager',member='InterfacesAdded'"
method return time=1750287421.989931 sender=org.freedesktop.DBus -> destination=:1.166 serial=178 reply_serial=298
method call time=1750287421.990135 sender=:1.166 -> destination=org.freedesktop.DBus serial=299 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender=':1.230',path='/org/example/monitor',interface='org.freedesktop.DBus.ObjectManager',member='InterfacesRemoved'"
method return time=1750287421.990162 sender=org.freedesktop.DBus -> destination=:1.166 serial=179 reply_serial=299
method call time=1750287421.990350 sender=:1.166 -> destination=org.freedesktop.DBus serial=300 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender=':1.230',path_namespace='/org/example/monitor'"
method return time=1750287421.990378 sender=org.freedesktop.DBus -> destination=:1.166 serial=180 reply_serial=300

// Tries to GetManagedObjects
method call time=1750287421.990468 sender=:1.166 -> destination=:1.230 serial=301 path=/org/example/monitor; interface=org.freedesktop.DBus.ObjectManager; member=GetManagedObjects

// A while later, it errors out
error time=1750287447.016276 sender=:1.230 -> destination=:1.166 error_name=org.freedesktop.DBus.Error.UnknownObject reply_serial=301
   string "Unknown object '/org/example/monitor'."

Additional context
Running on Ubuntu 24.04.2. I enabled experimental mode on bluetoothd, and have been able to add a monitor from bluetoothctl, so this should be working.

I'm building with Bazel, but I don't think that should matter?

cc_library(
    name = "sdbus-cpp",
    srcs = glob([
        "src/*.h",
        "src/*.c",
        "src/*.cpp",
    ]),
    hdrs = glob([
        "include/sdbus-c++/**/*.h",
        "include/sdbus-c++/**/*.inl",
    ]),
    includes = ["include"],
    copts = [
        '-DSDBUS_HEADER=\"<systemd/sd-bus.h>\"',
    ],
    linkopts = select({
        "@//tools/toolchains:linux_aarch64_config": [],
        "//conditions:default": [
            "-lsystemd",
        ],
    }),
)

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