I'm developing a Qt 6.4.0 application that runs on Ubuntu 22.04 (Jammy Jellyfish), and it uses Qt OPC UA to connect to several PLCs on the network. After running some hours, my application crashes. Long story short, I discovered it happens when a PLC goes offline. To be sure, I simulate a host going offline with:
sudo ufw reject out to 192.168.1.110
sudo ufw reject in from 192.168.1.110
And I can replicate the crash. Inspecting the issue with a debugger, I found out the problem is at line 42096 of open62541.c:
if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) {
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
"SecureChannel must be connected before sending requests");
return UA_STATUSCODE_BADSERVERNOTCONNECTED;
}
I'm puzzled they didn't check for the value of the pointer (in fact it's 0x00
as you can see in the image).
This happens when I try to read anything from the remote host.
If I disable the readings, I can correctly detect the host is down and reconnect to it after removing the rules.
Here how I read the values:
void MyOpcUa::readAll()
{
QMapIterator<QString, Node_t> i(_mapOpcNodes);
while (i.hasNext())
{
i.next();
Node_t node = i.value();
if (node.enableRead)
{
node.updated = false;
node.node->readValueAttribute();
}
}
}
void MyOpcUa::insertNode(QString key, QString id, bool enableRead)
{
Node_t node;
node.node = _opcUaClient->node(id);
node.value = QVariant();
node.updated = false;
node.enableRead = enableRead;
_mapOpcNodes.insert(key, node);
connect(node.node, &QOpcUaNode::attributeRead, this, &MyOpcUa::handleAttributes);
}
I call readAll()
if the host seems online. I rely on the &QOpcUaClient::disconnected
signal. But this is emitted some time after.
Since the readValueAttribute()
function is asynchronous (it fires the attributeRead
signal after some time), the error happens outside my code—between the call of the readValueAttribute()
and the slot.
How should I prevent such a crash?