PDA

View Full Version : Problem with asyncCall in DBus



Lorne Sturtevant
12th April 2012, 18:50
I'm trying use QDBusConnection::asyncCall() but it is not working correctly. I make the call and the server receives it and sends back a reply. I use a QDBusPendingCallWatcher to listen for the reply. The finished() signal of the watcher does not get called unless I tell the watcher to waitForFinished(). This defeats the entire purpose of using the asyncCall() since waitForFinished() blocks. Here's an example of what I'm doing. This is based on the example code in the QDBusPendingCallWatcher API documentation.



void Controller::makeCall() {

QDBusMessage msg = QDBusMessage::createMethodCall(serviceName, objectPath, "", method);
QDBusPendingCall asyncCall = connection.asyncCall(msg, timeout);

QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCall, this);
QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
this, SLOT(callFinishedSlot(QDBusPendingCallWatcher*)));

// with this commented out, callFinishedSlot() is never called. If the comment is removed, callFinishedSlot() is called
//watcher->waitForFinished();
}

void Controller::callFinishedSlot(QDBusPendingCallWatch er *watcher) {

LOG_DEBUG("got finished");
} // callFinishedSlot()


I've also tried to do the same thing using QDBusInterface::asyncCall() instead of using QDBusConnection::asyncCall(), but I get the same result. The call to watcher->waitForFinished() is required to get a result.

galap
14th January 2014, 10:12
I am not sure, but some sources says that your asynchronous call can finish before you actually connect to a slot. You can try cover your asynchronous method and signal/slot connection in debug messages to check if it is actually the case.

I failed to find any proof or disproof of this problem in QT documentation.

galap
14th January 2014, 13:21
Quote from http://www.qtdeveloperdays.com/northamerica/2013/asynchronous-programming-and-more-qt-5-and-c11:

Pending objects such as QDBusPendingCallWatcher might finish processing before connecting to a slot.

Link has presentation attached with this aproach:

QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(jobPath);
if (watcher->isFinished()) {
onJobPathFinished(watcher)
} else {
connect(watcher, &QDBusPendingCallWatcher::finished, onJobPathFinished);
}

But again I am not sure if this aproach garantee that connection to a slot will finish before DBus call finishes.

anda_skoa
14th January 2014, 15:37
I am not sure, but some sources says that your asynchronous call can finish before you actually connect to a slot.

Only if you return to the event loop or explicitly cause event processing in between.

Without event processing there is no way for the reply to be read from the D-Bus connection socket.

Cheers,
_

P.S.: the thread is almost two years old :)

galap
15th January 2014, 11:09
Good to know. Makes me more relaxed :). But original case is unresolved anyway. The only thing that cross my mind - mainloop and posted hadler run in different threads.
Thanks for help anyway!

--
P.S.: Was forced to use pending call watcher only last week and this question took place.