abbterra: fix TCP discovery SEGV + restore checkReachableRegister
Two coupled fixes so the ABB Terra AC can be added over Modbus TCP:
- Restore checkReachableRegister ("serialNumber") in the register JSON.
The libnymea-modbus 1.15 code generator *requires* it — without it the
connection classes (abbterramodbustcpconnection.h) are never generated and
the plugin fails to build. Reverts the false lead in 4fa06df. The register
is valid: mbpoll confirms holding reg 16384 (uint64) responds at slave 2.
- Fix a use-after-free in AbbTerraTcpDiscovery::cleanupConnection() that
SIGSEGV'd nymead during network discovery whenever any Modbus device on the
LAN answered on :502 with an exception (e.g. "illegal data address"). The
method is invoked from several of the connection's own signals; it now
bails out on the second (re-entrant) call and disconnects the connection's
signals before disconnectDevice(), so the teardown can no longer re-enter
while the QModbusReply "finished" handler is still dereferencing the reply.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4fa06df2d0
commit
28c348669c
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"className": "AbbTerra",
|
"className": "AbbTerra",
|
||||||
"protocol": "BOTH",
|
"protocol": "BOTH",
|
||||||
|
"checkReachableRegister": "serialNumber",
|
||||||
"endianness": "BigEndian",
|
"endianness": "BigEndian",
|
||||||
"stringEndianness": "BigEndian",
|
"stringEndianness": "BigEndian",
|
||||||
"errorLimitUntilNotReachable": 3,
|
"errorLimitUntilNotReachable": 3,
|
||||||
|
|||||||
@ -92,7 +92,24 @@ void AbbTerraTcpDiscovery::checkNetworkDevice(const QHostAddress &address)
|
|||||||
|
|
||||||
void AbbTerraTcpDiscovery::cleanupConnection(AbbTerraModbusTcpConnection *connection)
|
void AbbTerraTcpDiscovery::cleanupConnection(AbbTerraModbusTcpConnection *connection)
|
||||||
{
|
{
|
||||||
m_connections.removeAll(connection);
|
// A single reachability failure fans out into several signals
|
||||||
|
// (reachableChanged, checkReachabilityFailed, connectionErrorOccurred), each
|
||||||
|
// wired to this method. removeAll() returns the number of entries actually
|
||||||
|
// removed, so the first call tears the connection down and every subsequent
|
||||||
|
// (possibly re-entrant) call becomes a no-op.
|
||||||
|
if (m_connections.removeAll(connection) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Stop reacting to any further signals from this connection (and its Modbus
|
||||||
|
// master) before tearing it down. Otherwise disconnectDevice() below can
|
||||||
|
// synchronously emit reachableChanged()/connectionErrorOccurred() and
|
||||||
|
// re-enter this method while we are still inside one of the connection's own
|
||||||
|
// signal handlers (e.g. the QModbusReply "finished" lambda that keeps
|
||||||
|
// dereferencing the reply after the emit) — a use-after-free that crashes
|
||||||
|
// nymead with SIGSEGV during network discovery.
|
||||||
|
disconnect(connection, nullptr, this, nullptr);
|
||||||
|
disconnect(connection->modbusTcpMaster(), nullptr, this, nullptr);
|
||||||
|
|
||||||
connection->disconnectDevice();
|
connection->disconnectDevice();
|
||||||
connection->deleteLater();
|
connection->deleteLater();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user