diff -r e24348a560a6 -r b72c6db6890b src/dbus/qdbusintegrator.cpp --- a/src/dbus/qdbusintegrator.cpp Fri Jun 11 14:24:45 2010 +0300 +++ b/src/dbus/qdbusintegrator.cpp Wed Jun 23 19:07:03 2010 +0300 @@ -523,7 +523,7 @@ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message); - qDBusDebug() << d << "got message:" << amsg; + qDBusDebug() << d << "got message (signal):" << amsg; return d->handleMessage(amsg) ? DBUS_HANDLER_RESULT_HANDLED : @@ -1687,15 +1687,31 @@ void QDBusConnectionPrivate::waitForFinished(QDBusPendingCallPrivate *pcall) { Q_ASSERT(pcall->pending); - QDBusDispatchLocker locker(PendingCallBlockAction, this); - q_dbus_pending_call_block(pcall->pending); - // QDBusConnectionPrivate::processFinishedCall() is called automatically + Q_ASSERT(!pcall->autoDelete); + //Q_ASSERT(pcall->mutex.isLocked()); // there's no such function + + if (pcall->waitingForFinished) { + // another thread is already waiting + pcall->waitForFinishedCondition.wait(&pcall->mutex); + } else { + pcall->waitingForFinished = true; + pcall->mutex.unlock(); + + { + QDBusDispatchLocker locker(PendingCallBlockAction, this); + q_dbus_pending_call_block(pcall->pending); + // QDBusConnectionPrivate::processFinishedCall() is called automatically + } + pcall->mutex.lock(); + } } void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) { QDBusConnectionPrivate *connection = const_cast(call->connection); + QMutexLocker locker(&call->mutex); + QDBusMessage &msg = call->replyMessage; if (call->pending) { // decode the message @@ -1725,6 +1741,12 @@ qDBusDebug() << "Deliver failed!"; } + if (call->pending) + q_dbus_pending_call_unref(call->pending); + call->pending = 0; + + locker.unlock(); + // Are there any watchers? if (call->watcherHelper) call->watcherHelper->emitSignals(msg, call->sentMessage); @@ -1732,12 +1754,10 @@ if (msg.type() == QDBusMessage::ErrorMessage) emit connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage); - if (call->pending) - q_dbus_pending_call_unref(call->pending); - call->pending = 0; - - if (call->autoDelete) + if (call->autoDelete) { + Q_ASSERT(!call->waitingForFinished); // can't wait on a call with autoDelete! delete call; + } } int QDBusConnectionPrivate::send(const QDBusMessage& message) @@ -1879,17 +1899,14 @@ { if (isServiceRegisteredByThread(message.service())) { // special case for local calls - QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate; - pcall->sentMessage = message; + QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); pcall->replyMessage = sendWithReplyLocal(message); - pcall->connection = this; return pcall; } checkThread(); - QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate; - pcall->sentMessage = message; + QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); pcall->ref = 0; QDBusError error; @@ -1913,7 +1930,6 @@ q_dbus_message_unref(msg); pcall->pending = pending; - pcall->connection = this; q_dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall, 0); return pcall;