[Patch] - Fundstelle potentielles Speicherleak in 00_MQTT2_CLIENT.pm

Begonnen von DS_Starter, 22 September 2026, 13:50:09

Vorheriges Thema - Nächstes Thema

DS_Starter

Hallo Rudi,

ich gehe nach und nach alle bei mir im Einsatz befindlichen Module inkl. meiner eigenen hinsichtlich potentieller Speicherleaks durch.
Dabei bin ich (bzw. mein Helferlein) im Modul 00_MQTT2_CLIENT.pm fündig geworden und habe die nachfolgenden Korrekturen eingebaut.
Bei mir gibt es mehrere FHEM Instanzen, manche zeigen Speicherwachstum über die Zeit, andere nicht.
Das Modul ist bei mir getestet und erfolgreich im Einsatz. Der Fund ist nur ein Bausteinchen und es wird noch weitere geben.
Wegen der geringen Größe habe ich das Modul mit den beschriebenen Patches gleich hier angehängt.

Zirkuläre Referenz in sendHash
Fundstelle: MQTT2_CLIENT_doPublish, Zeile 638:

push(@{$hash->{sendHash}}, \@_);\@_ ist eine Referenz auf das tatsächliche @_-Array des Funktionsaufrufs.
@_[0] enthält $hash selbst (Signatur: my ($hash, $topic, $val, $retain, $immediate) = @_). Das ergibt:
$hash → {sendHash} → [ [\@_] → $hash, ... ]
                              ↑
                     Element [0] ist $hash!
Diese Kette wird in MQTT2_CLIENT_Disco nicht aufgebrochen. Beim Device-Delete sinkt der Refcount von $hash durch delete $defs{$name} um 1 — aber da {sendHash} weiterhin eine Referenz hält, erreicht er nie 0 -> Speicherleck.

FIX:
Änderung 1 — MQTT2_CLIENT_doPublish (Zeile 638):
# alt
push(@{$hash->{sendHash}}, \@_);

# neu
push(@{$hash->{sendHash}}, [$topic, $val, $retain]);

Änderung 2 — MQTT2_CLIENT_doinit, connecting == 3 (Zeile 237–238):
Die Replay-Schleife greift auf [1], [2], [3] zu, weil [ 0 ] bisher $hash war. Nach Fix 1 verschiebt sich das.
# alt
map { MQTT2_CLIENT_doPublish($hash,$_->[1],$_->[2],$_->[3]) }
          @{$hash->{sendHash}};

# neu
map { MQTT2_CLIENT_doPublish($hash,$_->[0],$_->[1],$_->[2]) }
          @{$hash->{sendHash}};
                 
Änderung 3 — MQTT2_CLIENT_Disco (nach Zeile 291, delete($hash->{BUF})):
Aufräumen für den isUndef-Pfad.
# alt
delete($hash->{BUF});

# neu
delete($hash->{BUF});
delete($hash->{sendHash}) if($isUndef);

inConnectFn nicht in Disco gelöscht
Fundstelle: MQTT2_CLIENT_connect setzt $hash->{inConnectFn} = 1, aber Disco (Zeile 279–302) räumt es nicht auf.

Konsequenz: Wenn während eines laufenden connectFn-Zyklus ein Disco ausgelöst wird, bleibt das Flag erhalten. Beim nächsten Verbindungsversuch trifft die Guard-Bedingung:

return if($hash->{inConnectFn}); # called by readyFnund der Reconnect wird blockiert, bis set connect manuell ausgeführt wird. Kein direkter Speicherleck, aber korrektiv.

Fix:
Eine Zeile im Cleanup-Block von MQTT2_CLIENT_Disco, direkt bei den anderen delete-Aufrufen am Ende.
# alt
  delete $hash->{waitingForConnack};
  delete $hash->{waitingForPingRespSince};

# neu
  delete $hash->{waitingForConnack};
  delete $hash->{waitingForPingRespSince};
  delete $hash->{inConnectFn};

LG,
Heiko


Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter