QDBusServer: delay processing of D-Bus messages

We must ensure that QDBusServer's newConnection() signal has been
processed by the application, before starting processing messages on it.

Task-number: QTBUG-55087
Change-Id: I595329b2f98788dbf9f40558b8c230c0c0817ef8
Reviewed-by: Timo Jyrinki <timo.jyrinki@iki.fi>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alberto Mardegan 2016-08-09 17:01:37 +03:00 committed by Timo Jyrinki
parent 43a710df63
commit a32217cb55
4 changed files with 33 additions and 20 deletions

View File

@ -68,24 +68,6 @@ static void preventDllUnload();
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
// can be replaced with a lambda in Qt 5.7
class QDBusConnectionDispatchEnabler : public QObject
{
Q_OBJECT
QDBusConnectionPrivate *con;
public:
QDBusConnectionDispatchEnabler(QDBusConnectionPrivate *con) : con(con) {}
public slots:
void execute()
{
con->setDispatchEnabled(true);
if (!con->ref.deref())
con->deleteLater();
deleteLater();
}
};
struct QDBusConnectionManager::ConnectionRequestData
{
enum RequestType {
@ -1281,8 +1263,6 @@ QByteArray QDBusConnection::localMachineId()
QT_END_NAMESPACE
#include "qdbusconnection.moc"
#ifdef Q_OS_WIN
# include <qt_windows.h>

View File

@ -375,6 +375,25 @@ extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNod
const QDBusMessage &msg);
extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node,
const QDBusMessage &msg);
// can be replaced with a lambda in Qt 5.7
class QDBusConnectionDispatchEnabler : public QObject
{
Q_OBJECT
QDBusConnectionPrivate *con;
public:
QDBusConnectionDispatchEnabler(QDBusConnectionPrivate *con) : con(con) {}
public slots:
void execute()
{
con->setDispatchEnabled(true);
if (!con->ref.deref())
con->deleteLater();
deleteLater();
}
};
#endif // QT_BOOTSTRAPPED
QT_END_NAMESPACE

View File

@ -309,9 +309,21 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v
// setPeer does the error handling for us
QDBusErrorInternal error;
newConnection->setPeer(connection, error);
newConnection->setDispatchEnabled(false);
// this is a queued connection and will resume in the QDBusServer's thread
emit serverConnection->newServerConnection(newConnection);
// we've disabled dispatching of events, so now we post an event to the
// QDBusServer's thread in order to enable it after the
// QDBusServer::newConnection() signal has been received by the
// application's code
newConnection->ref.ref();
QReadLocker serverLock(&serverConnection->lock);
QDBusConnectionDispatchEnabler *o = new QDBusConnectionDispatchEnabler(newConnection);
QTimer::singleShot(0, o, SLOT(execute()));
if (serverConnection->serverObject)
o->moveToThread(serverConnection->serverObject->thread());
}
void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnection)

View File

@ -97,6 +97,7 @@ QDBusServer::QDBusServer(QObject *parent)
*/
QDBusServer::~QDBusServer()
{
QWriteLocker locker(&d->lock);
if (QDBusConnectionManager::instance()) {
QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
Q_FOREACH (const QString &name, d->serverConnectionNames) {
@ -104,6 +105,7 @@ QDBusServer::~QDBusServer()
}
d->serverConnectionNames.clear();
}
d->serverObject = nullptr;
d->ref.store(0);
d->deleteLater();
}