summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPeter Seiderer <ps.report@gmx.net>2013-06-17 18:56:08 (GMT)
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-03 01:41:37 (GMT)
commitb638c7bf7309ea6b29f4043c86d790fbc20c006e (patch)
tree1b5ded43568419604c31ae53a245964919c80e85 /src
parenta9b48e98b8e90a0ccc729b00336e59acc86ad9ca (diff)
downloadQt-b638c7bf7309ea6b29f4043c86d790fbc20c006e.zip
Qt-b638c7bf7309ea6b29f4043c86d790fbc20c006e.tar.gz
Qt-b638c7bf7309ea6b29f4043c86d790fbc20c006e.tar.bz2
Remove QDBusPendingCallPrivate::autoDelete logic.
First step to fix race condition about deleting QDBusPendingCallPrivate. In a multithreaded application on a slow/single core cpu the following race (and segmentation fault) can occur: First thread A is running: A: QDBusPendingReply<> reply = pi->asyncCallWithArgumentList(method, argumentList); Then when the dbus answer arrives thread B will call: B: QDBusConnectionPrivate::processFinishedCall() B: ... B: locker.unlock() and runs until here, go on with thread A: A: reply.waitForFinished(); A: QDBusPendingCallPrivate::waitForFinished() A: { A: QMutexLocker locker(&mutex); A: if (replyMessage.type() != QDBusMessage::InvalidMessage) A: return; which returns immediately (mutex acquired, replyMessage alread set), now reply goes out of scope (destructor called) and QDBusPendingCall::d's destructor of type QExplicitlySharedDataPointer<QDBusPendingCallPrivate> deletes the reference counted object QDBusPendingCallPrivate. Now thread B continues, still in processFinishedCall() B: if (call->watcherHelper) B: call->watcherHelper->emitSignals(msg, call->sentMessage); B: B: if (msg.type() == QDBusMessage::ErrorMessage) B: emit connection->callWithCallbackFailed(QDBusError(msg), B: call->sentMessage); accessing alread deleted object QDBusPendingCallPrivate via call->... Fixed QDBusPendingCallPrivate deletion by proper reference counting will be done in the next commit. Task-number: QTBUG-27809 Change-Id: I15b3f0242471b62eaafadc763fb6a33339ff2fe1 (cherry-picked from qtbase commit 72ecf5a7ecb688a7e19cbc2f70e358a94d02edf7) Reviewed-by: Peter Seiderer <ps.report@gmx.net> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r--src/dbus/qdbusintegrator.cpp7
-rw-r--r--src/dbus/qdbuspendingcall_p.h3
2 files changed, 1 insertions, 9 deletions
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index ae67079..a91ba0e 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -1766,7 +1766,6 @@ static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
void QDBusConnectionPrivate::waitForFinished(QDBusPendingCallPrivate *pcall)
{
Q_ASSERT(pcall->pending);
- Q_ASSERT(!pcall->autoDelete);
//Q_ASSERT(pcall->mutex.isLocked()); // there's no such function
if (pcall->waitingForFinished) {
@@ -1840,11 +1839,6 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
if (msg.type() == QDBusMessage::ErrorMessage)
emit connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage);
-
- if (call->autoDelete) {
- Q_ASSERT(!call->waitingForFinished); // can't wait on a call with autoDelete!
- delete call;
- }
}
int QDBusConnectionPrivate::send(const QDBusMessage& message)
@@ -2063,7 +2057,6 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj
return 1;
}
- pcall->autoDelete = true;
pcall->ref.ref();
pcall->setReplyCallback(receiver, returnMethod);
diff --git a/src/dbus/qdbuspendingcall_p.h b/src/dbus/qdbuspendingcall_p.h
index 46861ec..d797b5f 100644
--- a/src/dbus/qdbuspendingcall_p.h
+++ b/src/dbus/qdbuspendingcall_p.h
@@ -85,7 +85,6 @@ public:
QList<int> metaTypes;
int methodIdx;
- bool autoDelete;
// }
mutable QMutex mutex;
@@ -103,7 +102,7 @@ public:
// }
QDBusPendingCallPrivate(const QDBusMessage &sent, QDBusConnectionPrivate *connection)
- : sentMessage(sent), connection(connection), autoDelete(false), watcherHelper(0), pending(0), waitingForFinished(false)
+ : sentMessage(sent), connection(connection), watcherHelper(0), pending(0), waitingForFinished(false)
{ }
~QDBusPendingCallPrivate();
bool setReplyCallback(QObject *target, const char *member);