summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJannis Voelker <jannis.voelker@basyskom.com>2024-01-26 10:19:25 +0100
committerJannis Voelker <jannis.voelker@basyskom.com>2024-01-26 12:49:59 +0100
commitabbd8b9e0d0dec8bcfe020f31f54e41544e8d1b4 (patch)
treef3dd62352587929dca5122029173f8940091687a
parentb1529861a484b833ef895c72d7b24f21e9f73ee3 (diff)
Fix backend segfault caused by race condition
Some of the backend methods were not checking the open62541 client for nullptr. This could cause a segfault if there were any requests already in the queue when the client was disconnected. Change-Id: I7fc70d27ad7b0e2fab092a2ce18d3c80ca3e22be Pick-to: 6.7 6.6 6.5 Reviewed-by: Frank Meerkoetter <frank.meerkoetter@basyskom.com>
-rw-r--r--src/plugins/opcua/open62541/qopen62541backend.cpp114
1 files changed, 112 insertions, 2 deletions
diff --git a/src/plugins/opcua/open62541/qopen62541backend.cpp b/src/plugins/opcua/open62541/qopen62541backend.cpp
index fd6e11d..7be362b 100644
--- a/src/plugins/opcua/open62541/qopen62541backend.cpp
+++ b/src/plugins/opcua/open62541/qopen62541backend.cpp
@@ -58,6 +58,18 @@ void Open62541AsyncBackend::readAttributes(quint64 handle, UA_NodeId id, QOpcUa:
{
UaDeleter<UA_NodeId> nodeIdDeleter(&id, UA_NodeId_clear);
+ if (!m_uaclient) {
+ QList<QOpcUaReadResult> resultMetadata;
+
+ qt_forEachAttribute(attr, [&](QOpcUa::NodeAttribute attribute){
+ QOpcUaReadResult temp;
+ temp.setAttribute(attribute);
+ resultMetadata.push_back(temp);
+ });
+ emit attributesRead(handle, resultMetadata, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
UA_ReadRequest req;
UA_ReadRequest_init(&req);
UaDeleter<UA_ReadRequest> requestDeleter(&req, UA_ReadRequest_clear);
@@ -105,6 +117,12 @@ void Open62541AsyncBackend::readAttributes(quint64 handle, UA_NodeId id, QOpcUa:
void Open62541AsyncBackend::writeAttribute(quint64 handle, UA_NodeId id, QOpcUa::NodeAttribute attrId, QVariant value, QOpcUa::Types type, QString indexRange)
{
+ if (!m_uaclient) {
+ UA_NodeId_clear(&id);
+ emit attributeWritten(handle, attrId, value, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
if (type == QOpcUa::Types::Undefined && attrId != QOpcUa::NodeAttribute::Value)
type = attributeIdToTypeId(attrId);
@@ -139,6 +157,11 @@ void Open62541AsyncBackend::writeAttributes(quint64 handle, UA_NodeId id, QOpcUa
{
UaDeleter<UA_NodeId> nodeIdDeleter(&id, UA_NodeId_clear);
+ if (!m_uaclient) {
+ emit attributeWritten(handle, QOpcUa::NodeAttribute::None, QVariant(), QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
if (toWrite.size() == 0) {
qCWarning(QT_OPCUA_PLUGINS_OPEN62541) << "No values to be written";
emit attributeWritten(handle, QOpcUa::NodeAttribute::None, QVariant(), QOpcUa::UaStatusCode::BadNothingToDo);
@@ -178,6 +201,15 @@ void Open62541AsyncBackend::enableMonitoring(quint64 handle, UA_NodeId id, QOpcU
{
UaDeleter<UA_NodeId> nodeIdDeleter(&id, UA_NodeId_clear);
+ if (!m_uaclient) {
+ qt_forEachAttribute(attr, [&](QOpcUa::NodeAttribute attribute){
+ QOpcUaMonitoringParameters s;
+ s.setStatusCode(QOpcUa::UaStatusCode::BadDisconnect);
+ emit monitoringEnableDisable(handle, attribute, true, s);
+ });
+ return;
+ }
+
QOpen62541Subscription *usedSubscription = nullptr;
// Create a new subscription if necessary
@@ -227,6 +259,15 @@ void Open62541AsyncBackend::enableMonitoring(quint64 handle, UA_NodeId id, QOpcU
void Open62541AsyncBackend::disableMonitoring(quint64 handle, QOpcUa::NodeAttributes attr)
{
+ if (!m_uaclient) {
+ qt_forEachAttribute(attr, [&](QOpcUa::NodeAttribute attribute){
+ QOpcUaMonitoringParameters s;
+ s.setStatusCode(QOpcUa::UaStatusCode::BadDisconnect);
+ emit monitoringEnableDisable(handle, attribute, false, s);
+ });
+ return;
+ }
+
qt_forEachAttribute(attr, [&](QOpcUa::NodeAttribute attribute){
QOpen62541Subscription *sub = getSubscriptionForItem(handle, attribute);
if (sub) {
@@ -245,6 +286,13 @@ void Open62541AsyncBackend::disableMonitoring(quint64 handle, QOpcUa::NodeAttrib
void Open62541AsyncBackend::modifyMonitoring(quint64 handle, QOpcUa::NodeAttribute attr, QOpcUaMonitoringParameters::Parameter item, QVariant value)
{
+ if (!m_uaclient) {
+ QOpcUaMonitoringParameters p;
+ p.setStatusCode(QOpcUa::UaStatusCode::BadDisconnect);
+ emit monitoringStatusChanged(handle, attr, item, p);
+ return;
+ }
+
QOpen62541Subscription *subscription = getSubscriptionForItem(handle, attr);
if (!subscription) {
qCWarning(QT_OPCUA_PLUGINS_OPEN62541) << "Could not modify" << item << ", the monitored item does not exist";
@@ -296,6 +344,13 @@ bool Open62541AsyncBackend::removeSubscription(UA_UInt32 subscriptionId)
void Open62541AsyncBackend::callMethod(quint64 handle, UA_NodeId objectId, UA_NodeId methodId, QList<QOpcUa::TypedVariant> args)
{
+ if (!m_uaclient) {
+ emit methodCallFinished(handle, Open62541Utils::nodeIdToQString(methodId), QVariant(), QOpcUa::UaStatusCode::BadDisconnect);
+ UA_NodeId_clear(&objectId);
+ UA_NodeId_clear(&methodId);
+ return;
+ }
+
UA_Variant *inputArgs = nullptr;
if (args.size()) {
@@ -330,6 +385,12 @@ void Open62541AsyncBackend::callMethod(quint64 handle, UA_NodeId objectId, UA_No
void Open62541AsyncBackend::resolveBrowsePath(quint64 handle, UA_NodeId startNode, const QList<QOpcUaRelativePathElement> &path)
{
+ if (!m_uaclient) {
+ UA_NodeId_clear(&startNode);
+ emit resolveBrowsePathFinished(handle, {}, path, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
UA_TranslateBrowsePathsToNodeIdsRequest req;
UA_TranslateBrowsePathsToNodeIdsRequest_init(&req);
UaDeleter<UA_TranslateBrowsePathsToNodeIdsRequest> requestDeleter(
@@ -464,6 +525,11 @@ void Open62541AsyncBackend::findServers(const QUrl &url, const QStringList &loca
void Open62541AsyncBackend::readNodeAttributes(const QList<QOpcUaReadItem> &nodesToRead)
{
+ if (!m_uaclient) {
+ emit readNodeAttributesFinished({}, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
if (nodesToRead.size() == 0) {
emit readNodeAttributesFinished(QList<QOpcUaReadResult>(), QOpcUa::UaStatusCode::BadNothingToDo);
return;
@@ -501,6 +567,11 @@ void Open62541AsyncBackend::readNodeAttributes(const QList<QOpcUaReadItem> &node
void Open62541AsyncBackend::writeNodeAttributes(const QList<QOpcUaWriteItem> &nodesToWrite)
{
+ if (!m_uaclient) {
+ emit writeNodeAttributesFinished({}, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
if (nodesToWrite.isEmpty()) {
emit writeNodeAttributesFinished(QList<QOpcUaWriteResult>(), QOpcUa::UaStatusCode::BadNothingToDo);
return;
@@ -555,6 +626,11 @@ void Open62541AsyncBackend::writeNodeAttributes(const QList<QOpcUaWriteItem> &no
void Open62541AsyncBackend::readHistoryRaw(QOpcUaHistoryReadRawRequest request, QList<QByteArray> continuationPoints, bool releaseContinuationPoints, quint64 handle)
{
+ if (!m_uaclient) {
+ emit historyDataAvailable({}, {}, QOpcUa::UaStatusCode::BadDisconnect, handle);
+ return;
+ }
+
if (!continuationPoints.empty() && continuationPoints.size() != request.nodesToRead().size()) {
emit historyDataAvailable({}, {}, QOpcUa::UaStatusCode::BadInternalError, handle);
return;
@@ -604,6 +680,11 @@ void Open62541AsyncBackend::readHistoryRaw(QOpcUaHistoryReadRawRequest request,
void Open62541AsyncBackend::readHistoryEvents(const QOpcUaHistoryReadEventRequest &request, const QList<QByteArray> &continuationPoints,
bool releaseContinuationPoints, quint64 handle)
{
+ if (!m_uaclient) {
+ emit historyDataAvailable({}, {}, QOpcUa::UaStatusCode::BadDisconnect, handle);
+ return;
+ }
+
if (!continuationPoints.empty() && continuationPoints.size() != request.nodesToRead().size()) {
emit historyDataAvailable({}, {}, QOpcUa::UaStatusCode::BadInternalError, handle);
return;
@@ -655,6 +736,11 @@ void Open62541AsyncBackend::readHistoryEvents(const QOpcUaHistoryReadEventReques
void Open62541AsyncBackend::addNode(const QOpcUaAddNodeItem &nodeToAdd)
{
+ if (!m_uaclient) {
+ emit addNodeFinished(nodeToAdd.requestedNewNodeId(), {}, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
UA_AddNodesRequest req;
UA_AddNodesRequest_init(&req);
UaDeleter<UA_AddNodesRequest> requestDeleter(&req, UA_AddNodesRequest_clear);
@@ -699,6 +785,11 @@ void Open62541AsyncBackend::addNode(const QOpcUaAddNodeItem &nodeToAdd)
void Open62541AsyncBackend::deleteNode(const QString &nodeId, bool deleteTargetReferences)
{
+ if (!m_uaclient) {
+ emit deleteNodeFinished(nodeId, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
UA_DeleteNodesRequest request;
UA_DeleteNodesRequest_init(&request);
UaDeleter<UA_DeleteNodesRequest> requestDeleter(&request, UA_DeleteNodesRequest_clear);
@@ -728,6 +819,13 @@ void Open62541AsyncBackend::deleteNode(const QString &nodeId, bool deleteTargetR
void Open62541AsyncBackend::addReference(const QOpcUaAddReferenceItem &referenceToAdd)
{
+ if (!m_uaclient) {
+ emit addReferenceFinished(referenceToAdd.sourceNodeId(), referenceToAdd.referenceTypeId(),
+ referenceToAdd.targetNodeId(), referenceToAdd.isForwardReference(),
+ QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
UA_AddReferencesRequest request;
UA_AddReferencesRequest_init(&request);
UaDeleter<UA_AddReferencesRequest> requestDeleter(&request, UA_AddReferencesRequest_clear);
@@ -767,6 +865,13 @@ void Open62541AsyncBackend::addReference(const QOpcUaAddReferenceItem &reference
void Open62541AsyncBackend::deleteReference(const QOpcUaDeleteReferenceItem &referenceToDelete)
{
+ if (!m_uaclient) {
+ emit deleteReferenceFinished(referenceToDelete.sourceNodeId(), referenceToDelete.referenceTypeId(),
+ referenceToDelete.targetNodeId(), referenceToDelete.isForwardReference(),
+ QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
UA_DeleteReferencesRequest request;
UA_DeleteReferencesRequest_init(&request);
UaDeleter<UA_DeleteReferencesRequest> requestDeleter(&request, UA_DeleteReferencesRequest_clear);
@@ -823,6 +928,11 @@ static void convertBrowseResult(UA_BrowseResult *src, size_t referencesSize, QLi
void Open62541AsyncBackend::browse(quint64 handle, UA_NodeId id, const QOpcUaBrowseRequest &request)
{
+ if (!m_uaclient) {
+ emit browseFinished(handle, {}, QOpcUa::UaStatusCode::BadDisconnect);
+ return;
+ }
+
UA_BrowseRequest uaRequest;
UA_BrowseRequest_init(&uaRequest);
UaDeleter<UA_BrowseRequest> requestDeleter(&uaRequest, UA_BrowseRequest_clear);
@@ -1215,7 +1325,7 @@ void Open62541AsyncBackend::cleanupSubscriptions()
void Open62541AsyncBackend::registerNodes(const QStringList &nodesToRegister)
{
if (!m_uaclient) {
- emit registerNodesFinished(nodesToRegister, {}, QOpcUa::UaStatusCode::BadNotConnected);
+ emit registerNodesFinished(nodesToRegister, {}, QOpcUa::UaStatusCode::BadDisconnect);
return;
}
@@ -1245,7 +1355,7 @@ void Open62541AsyncBackend::registerNodes(const QStringList &nodesToRegister)
void Open62541AsyncBackend::unregisterNodes(const QStringList &nodesToUnregister)
{
if (!m_uaclient) {
- emit unregisterNodesFinished(nodesToUnregister, QOpcUa::UaStatusCode::BadNotConnected);
+ emit unregisterNodesFinished(nodesToUnregister, QOpcUa::UaStatusCode::BadDisconnect);
return;
}