summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Stottlemyer <bstottle@ford.com>2019-05-13 12:18:43 -0400
committerBrett Stottlemyer <bstottle@ford.com>2019-05-21 12:31:06 +0000
commit5971d579e0069b2d244b171c6aa916f5111c84de (patch)
tree802927f341e2a985147f125c897cb5dab27dd9c7
parenta8a3088f1fcd7ff00e7748040473c27c4bea8dad (diff)
Fix return value propagation through proxies
A slot with return values returns a PendingCall object on the replica. If such a replica is used in a proxy, a client would get an invalid QVariant as the reply. This was because the proxy would try to return the pending- call, not wait for the slot return from the original source. This change fixes that issue. Change-Id: I1a25ed49ce51729dde4fa4593845946041493ea1 Reviewed-by: Brett Stottlemyer <bstottle@ford.com>
-rw-r--r--src/remoteobjects/qremoteobjectsourceio.cpp22
-rw-r--r--tests/auto/proxy_multiprocess/client/main.cpp7
2 files changed, 26 insertions, 3 deletions
diff --git a/src/remoteobjects/qremoteobjectsourceio.cpp b/src/remoteobjects/qremoteobjectsourceio.cpp
index c2dc70a..bde010b 100644
--- a/src/remoteobjects/qremoteobjectsourceio.cpp
+++ b/src/remoteobjects/qremoteobjectsourceio.cpp
@@ -42,6 +42,7 @@
#include "qremoteobjectpacket_p.h"
#include "qremoteobjectsource_p.h"
#include "qremoteobjectnode_p.h"
+#include "qremoteobjectpendingcall.h"
#include "qtremoteobjectglobal.h"
#include <QtCore/qstringlist.h>
@@ -240,11 +241,28 @@ void QRemoteObjectSourceIo::onServerRead(QObject *conn)
if (!QMetaType(typeId).sizeOf())
typeId = QVariant::Invalid;
QVariant returnValue(typeId, nullptr);
+ // If a Replica is used as a Source (which node->proxy() does) we can have a PendingCall return value.
+ // In this case, we need to wait for the pending call and send that.
+ if (source->m_api->typeName(index) == QByteArrayLiteral("QRemoteObjectPendingCall"))
+ returnValue = QVariant::fromValue<QRemoteObjectPendingCall>(QRemoteObjectPendingCall());
source->invoke(QMetaObject::InvokeMetaMethod, index, m_rxArgs, &returnValue);
// send reply if wanted
if (serialId >= 0) {
- serializeInvokeReplyPacket(m_packet, m_rxName, serialId, returnValue);
- connection->write(m_packet.array, m_packet.size);
+ if (returnValue.canConvert<QRemoteObjectPendingCall>()) {
+ QRemoteObjectPendingCall call = returnValue.value<QRemoteObjectPendingCall>();
+ // Watcher will be destroyed when connection is, or when the finished lambda is called
+ QRemoteObjectPendingCallWatcher *watcher = new QRemoteObjectPendingCallWatcher(call, connection);
+ QObject::connect(watcher, &QRemoteObjectPendingCallWatcher::finished, connection, [this, serialId, connection, watcher]() {
+ if (watcher->error() == QRemoteObjectPendingCall::NoError) {
+ serializeInvokeReplyPacket(this->m_packet, this->m_rxName, serialId, watcher->returnValue());
+ connection->write(m_packet.array, m_packet.size);
+ }
+ watcher->deleteLater();
+ });
+ } else {
+ serializeInvokeReplyPacket(m_packet, m_rxName, serialId, returnValue);
+ connection->write(m_packet.array, m_packet.size);
+ }
}
} else {
const int resolvedIndex = source->m_api->sourcePropertyIndex(index);
diff --git a/tests/auto/proxy_multiprocess/client/main.cpp b/tests/auto/proxy_multiprocess/client/main.cpp
index 4874fb1..f37821f 100644
--- a/tests/auto/proxy_multiprocess/client/main.cpp
+++ b/tests/auto/proxy_multiprocess/client/main.cpp
@@ -72,6 +72,8 @@ private Q_SLOTS:
qDebug() << "Verified expected initial states, sending start.";
auto reply = m_rep->start();
QVERIFY(reply.waitForFinished());
+ QVERIFY(reply.error() == QRemoteObjectPendingCall::NoError);
+ QCOMPARE(reply.returnValue(), QVariant::fromValue(true));
QSignalSpy advanceSpy(m_rep.data(), SIGNAL(advance()));
QVERIFY(advanceSpy.wait());
@@ -87,7 +89,10 @@ private Q_SLOTS:
void cleanupTestCase()
{
auto reply = m_rep->quit();
- QVERIFY(reply.waitForFinished());
+ // Don't verify the wait result, depending on the timing of the server and proxy
+ // closing it may return false. We just need this process to stay alive long
+ // enough for the packets to be sent.
+ reply.waitForFinished(5000);
}
private: