From f8b5142e3068d210393e7e4544c2e63577a313ac Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jun 2016 10:46:36 -0300 Subject: Fix race condition in tst_QDBusConnection::pendingCallWhenDisconnected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test sent a message and hoped that the "delete server" would cause the server object in the QDBusConnectionManager thread be deleted before it could receive and process the message. That's racy, because on some CI machines, it did and then sent back an error reply indicating the object sought was not found. Instead, let's use a child process that we can kill to make it exit at the right time. I've chosen to use dbus-daemon itself, because that lets us test the actual conditions that triggered the original bug: the daemon getting killed during a desktop session shutdown on Linux. Change-Id: I87e17314d8b24ae983b1fffd1454483aea87c921 Reviewed-by: Tony Sarajärvi --- .../dbus/qdbusconnection/tst_qdbusconnection.cpp | 39 +++++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'tests/auto/dbus/qdbusconnection') diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 9b16cf74a5..8dc94d3e07 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -40,6 +40,11 @@ #include #include +#ifdef Q_OS_UNIX +# include +# include +#endif + void MyObject::method(const QDBusMessage &msg) { path = msg.path(); @@ -1357,23 +1362,39 @@ void tst_QDBusConnection::callVirtualObjectLocal() void tst_QDBusConnection::pendingCallWhenDisconnected() { +#ifdef QT_NO_PROCESS + QSKIP("Test requires QProcess"); +#else if (!QCoreApplication::instance()) QSKIP("Test requires a QCoreApplication"); - QDBusServer *server = new QDBusServer; - QDBusConnection con = QDBusConnection::connectToPeer(server->address(), "disconnect"); - QTestEventLoop::instance().enterLoop(2); - QVERIFY(con.isConnected()); - QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), "method"); - QDBusPendingCall reply = con.asyncCall(message); + QProcess daemon; + daemon.start("dbus-daemon", QStringList() << "--session" << "--nofork" << "--print-address"); + QVERIFY2(daemon.waitForReadyRead(2000), + "Daemon didn't print its address in time; error: \"" + daemon.errorString().toLocal8Bit() + + "\"; stderr:\n" + daemon.readAllStandardError()); - delete server; + QString address = QString::fromLocal8Bit(daemon.readAll().trimmed()); + QDBusConnection con = QDBusConnection::connectToBus(address, "disconnect"); + QVERIFY2(con.isConnected(), (con.lastError().name() + ": " + con.lastError().message()).toLocal8Bit()); - QTestEventLoop::instance().enterLoop(2); + // confirm we're connected and we're alone in this bus + QCOMPARE(con.baseService(), QString(":1.0")); + + // kill the bus + daemon.terminate(); + daemon.waitForFinished(); + + // send something, which we should get an error with + QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", QString(), "ListNames"); + QDBusPendingCall reply = con.asyncCall(message); + + reply.waitForFinished(); QVERIFY(!con.isConnected()); QVERIFY(reply.isFinished()); QVERIFY(reply.isError()); - QVERIFY(reply.error().type() == QDBusError::Disconnected); + QCOMPARE(reply.error().type(), QDBusError::Disconnected); +#endif } QString MyObject::path; -- cgit v1.2.3