2

I'm trying to connect to a D-Bus signal this way:

bool result = QDBusConnection::systemBus().connect(
    "foo.bar",  // service
    "/foo/bar", // path 
    "foo.bar",  // interface
    "SignalSomething",
    this,
    SLOT(SignalSomethingSlot()));

if( !result )
{
    // Why!?
}

QDBusConnection::connect() returns a boolean, how do I get extended error information? If a check QDBusConnection::lastError() it returns no useful information (as QDBusError::isValid() is false).

lornova
  • 6,667
  • 9
  • 47
  • 74

2 Answers2

3

I had the same issue and it turned out that the slot I connected to had the wrong parameter types. They must match according to Qt's documentation and it looks like connect() verifies that, despite not explicitly mentioned.

Warning: The signal will only be delivered to the slot if the parameters match.

I suggest d-feet to list signals and check their parameter types. dbus-monitor does list signals, paths and such too, but not always the exact type of parameters.


One important observation though: I fixed the issue in my particular case by using different slot parameters than the actual signal has!

I wanted to connect to a com.ubuntu.Upstart0_6 signal mentioned here to detect when the screen in Ubuntu is locked/unlocked. dbusmonitor prints the following and d-feet shows parameters (String, Array of [String])

// dbusmonitor output
signal time=1529077633.579984 sender=:1.0 -> destination=(null destination) serial=809 path=/com/ubuntu/Upstart; interface=com.ubuntu.Upstart0_6; member=EventEmitted
   string "desktop-unlock"
   array [
   ]

Hence the signal should be of type

void screenLockChangedUbuntu(QString event, QVector<QString> args) // connect() -> false

This however made connect() return false. The solution was to remove the array parameter from the slot:

void screenLockChangedUbuntu(QString event) // works

I am aware that the array parameter was always empty, but I cannot explain why it only worked when removing it.

NexD.
  • 784
  • 6
  • 11
0

You could try these tricks:

1) Set QDBUS_DEBUG environment variable before running your application.

export QDBUS_DEBUG=1

2) Start dbus-monitor to see what's happening on the bus. You may need to set a global policy to be able to eavesdrop system bus depending on your distro.

Update:

Are you sure connecting to the system bus succeeded? If it fails you should probably check system.conf policy and possibly create own conf in system.d. This post might be helpful.

You could first connect to the system bus with QDBusConnection::connectToBus and check if it succeeded with QDBusConnection::isConnected. Only after that you try to connect to the signal and check if that succeeded.

QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::systemBus, myConnectionName);
if (bus.isConnected())
{
    if(!bus.connect( ... ))
    {
        // Connecting to signal failed
    }
}
else
{
    // Connecting to system bus failed
}
Community
  • 1
  • 1
talamaki
  • 5,324
  • 1
  • 27
  • 40
  • I tried both the tricks but they don't help as the problem is not on the bus but within QtDBus... – lornova May 19 '16 at 10:05
  • I updated my answer. Suspecting connecting to the system bus doesn't succeed. – talamaki May 20 '16 at 05:33
  • Yes it connects: I'm able to call methods on the same D-Bus interface. I just get an error trying to connect a SLOT to a D-Bus signal. But I don't want to be too specific and troubleshoot my specific scenario. I'd like to know if there is a way to get the reason for the failure. – lornova May 20 '16 at 08:09