diff options
author | Peter Seiderer <ps.report@gmx.net> | 2013-06-17 20:56:08 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-07-29 22:28:41 +0200 |
commit | 72ecf5a7ecb688a7e19cbc2f70e358a94d02edf7 (patch) | |
tree | 3095145b1b9fd2c13e1ca90f53f2899876e06fdb /src/dbus/qdbusintegrator.cpp | |
parent | 64e3bd481e5d54d555959ceecbd5c4576c571241 (diff) |
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
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/dbus/qdbusintegrator.cpp')
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 14 |
1 files changed, 0 insertions, 14 deletions
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index ed019cb662..4b9bfc3fc8 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1828,7 +1828,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) { @@ -1854,13 +1853,6 @@ void QDBusConnectionPrivate::waitForFinished(QDBusPendingCallPrivate *pcall) } } -// this function is called only in a Q_ASSERT -static inline Q_DECL_UNUSED bool waitingForFinishedIsSet(QDBusPendingCallPrivate *call) -{ - const QMutexLocker locker(&call->mutex); - return call->waitingForFinished; -} - void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) { QDBusConnectionPrivate *connection = const_cast<QDBusConnectionPrivate *>(call->connection); @@ -1909,11 +1901,6 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) if (msg.type() == QDBusMessage::ErrorMessage) emit connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage); - - if (call->autoDelete) { - Q_ASSERT(!waitingForFinishedIsSet(call)); // can't wait on a call with autoDelete! - delete call; - } } int QDBusConnectionPrivate::send(const QDBusMessage& message) @@ -2132,7 +2119,6 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj return 1; } - pcall->autoDelete = true; pcall->ref.ref(); pcall->setReplyCallback(receiver, returnMethod); |