summaryrefslogtreecommitdiffstats
path: root/src/dbus/qdbuspendingcall.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2010-05-18 13:58:24 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2010-05-24 19:09:31 (GMT)
commitfd256203708e79d64bad856e39bb5a43357bfd06 (patch)
tree7ec4edc7310b4a0724c3d6ffd3fce8a234f7c0c2 /src/dbus/qdbuspendingcall.cpp
parent314a36895e1a31dd2b62de265d9160238d96e512 (diff)
downloadQt-fd256203708e79d64bad856e39bb5a43357bfd06.zip
Qt-fd256203708e79d64bad856e39bb5a43357bfd06.tar.gz
Qt-fd256203708e79d64bad856e39bb5a43357bfd06.tar.bz2
Fix a race condition with QtDBus blocking for replies.
If an auxiliary thread tried to block on waiting for a reply, and at the same time the main thread handled the reply, there's room for a race condition. So ensure only one thread is stopped at dbus_pending_call_block(). The other thread(s) will be waiting on the QWaitCondition. It's not a race condition for the main thread to process (and finish processing) the reply while the auxiliary thread hasn't even started to wait. The code will ensure that the reply is properly seen. Task-Id: https://projects.maemo.org/bugzilla/show_bug.cgi?id=155306 Reviewed-By: Trust Me
Diffstat (limited to 'src/dbus/qdbuspendingcall.cpp')
-rw-r--r--src/dbus/qdbuspendingcall.cpp35
1 files changed, 27 insertions, 8 deletions
diff --git a/src/dbus/qdbuspendingcall.cpp b/src/dbus/qdbuspendingcall.cpp
index 3db5d9f..86b585d 100644
--- a/src/dbus/qdbuspendingcall.cpp
+++ b/src/dbus/qdbuspendingcall.cpp
@@ -208,6 +208,8 @@ void QDBusPendingCallPrivate::setMetaTypes(int count, const int *types)
void QDBusPendingCallPrivate::checkReceivedSignature()
{
+ // MUST BE CALLED WITH A LOCKED MUTEX!
+
if (replyMessage.type() == QDBusMessage::InvalidMessage)
return; // not yet finished - no message to
// validate against
@@ -230,6 +232,8 @@ void QDBusPendingCallPrivate::checkReceivedSignature()
void QDBusPendingCallPrivate::waitForFinished()
{
+ QMutexLocker locker(&mutex);
+
if (replyMessage.type() != QDBusMessage::InvalidMessage)
return; // already finished
@@ -310,7 +314,11 @@ QDBusPendingCall &QDBusPendingCall::operator=(const QDBusPendingCall &other)
bool QDBusPendingCall::isFinished() const
{
- return !d || (d->replyMessage.type() != QDBusMessage::InvalidMessage);
+ if (!d)
+ return true; // considered finished
+
+ QMutexLocker locker(&d->mutex);
+ return d->replyMessage.type() != QDBusMessage::InvalidMessage;
}
void QDBusPendingCall::waitForFinished()
@@ -329,7 +337,10 @@ void QDBusPendingCall::waitForFinished()
*/
bool QDBusPendingCall::isValid() const
{
- return d ? d->replyMessage.type() == QDBusMessage::ReplyMessage : false;
+ if (!d)
+ return false;
+ QMutexLocker locker(&d->mutex);
+ return d->replyMessage.type() == QDBusMessage::ReplyMessage;
}
/*!
@@ -343,7 +354,10 @@ bool QDBusPendingCall::isValid() const
*/
bool QDBusPendingCall::isError() const
{
- return d ? d->replyMessage.type() == QDBusMessage::ErrorMessage : true;
+ if (!d)
+ return true; // considered finished and an error
+ QMutexLocker locker(&d->mutex);
+ return d->replyMessage.type() == QDBusMessage::ErrorMessage;
}
/*!
@@ -356,8 +370,10 @@ bool QDBusPendingCall::isError() const
*/
QDBusError QDBusPendingCall::error() const
{
- if (d)
+ if (d) {
+ QMutexLocker locker(&d->mutex);
return d->replyMessage;
+ }
// not connected, return an error
QDBusError err = QDBusError(QDBusError::Disconnected,
@@ -378,7 +394,10 @@ QDBusError QDBusPendingCall::error() const
*/
QDBusMessage QDBusPendingCall::reply() const
{
- return d ? d->replyMessage : QDBusMessage::createError(error());
+ if (!d)
+ return QDBusMessage::createError(error());
+ QMutexLocker locker(&d->mutex);
+ return d->replyMessage;
}
#if 0
@@ -439,9 +458,8 @@ QDBusPendingCall QDBusPendingCall::fromCompletedCall(const QDBusMessage &msg)
QDBusPendingCallPrivate *d = 0;
if (msg.type() == QDBusMessage::ErrorMessage ||
msg.type() == QDBusMessage::ReplyMessage) {
- d = new QDBusPendingCallPrivate;
+ d = new QDBusPendingCallPrivate(QDBusMessage(), 0);
d->replyMessage = msg;
- d->connection = 0;
}
return QDBusPendingCall(d);
@@ -471,9 +489,10 @@ QDBusPendingCallWatcher::QDBusPendingCallWatcher(const QDBusPendingCall &call, Q
: QObject(*new QDBusPendingCallWatcherPrivate, parent), QDBusPendingCall(call)
{
if (d) { // QDBusPendingCall::d
+ QMutexLocker locker(&d->mutex);
if (!d->watcherHelper) {
d->watcherHelper = new QDBusPendingCallWatcherHelper;
- if (isFinished()) {
+ if (d->replyMessage.type() != QDBusMessage::InvalidMessage) {
// cause a signal emission anyways
QMetaObject::invokeMethod(d->watcherHelper, "finished", Qt::QueuedConnection);
}