[PATCH] - Blocking.pm: Immer Lesen verhindert FHEM-Lockup

Begonnen von jensb, 29 November 2015, 14:53:02

Vorheriges Thema - Nächstes Thema

jensb

Hallo Rudi,

anbei ein Patch für Blocking.pm, der einen Lockup von FHEM in folgendem Szenario verhindert:

  • 1x BlockingCall
  • Nx BlockingInformParent(waitForRead => 0), aber es kommen trotzdem (viele) Daten vom Parent
Die Folge ist, dass zunächst der TCP Receive Buffer im Child voll läuft und anschließend der TCP Transmit Buffer im Parent. Sobald letzteres passiert, hängt FHEM auf dem syswrite im Telnet Server und stürzt nach einiger Zeit meist auch ab.

Es hat einige Wochen gedauert, das herauszufinden. Als ich endlich mal in den Moment dabei war, als sich die Blockade gerade gebildet hat, war die Sache dank strace+losof+netstat zum Glück schnell klar.

Durch den Patch wird auch dann in BlockingInformParent vom Socket gelesen, wenn man sich im Child nicht für die Antwort vom Parent interessiert (kommt mir irgendwie bekannt vor ;)).

Das obige Szenario ist sicherlich ein Sonderfall, da BlockingCall oft als Single-Shot verwendet wird und die Blockade dann nicht auftritt (es sei denn die informFn liefert in ihrer 1. Antwort bereits mehrere Megabyte auf).

Der Patch enthält außerdem 3 geänderte Log-Ausgaben, die mir bei der Analyse geholfen haben. Zum einen steht in der Log-Ausgabe nun der Name der jeweiligen Blocking-Methode und zum anderen wird der Name der blockingFn bzw. informFn zusätzlich mit ausgegeben, da es inzwischen eine ganze Reihe Module gibt, die Blocking.pm verwenden und es so eindeutig ist, wer gerade aktiv ist.

Es würde ich mich sehr freuen, wenn du überprüfst, ob dieser Patch ganz oder in Teilen übernommen werden kann.

Danke und viele Grüße,

Jens


FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

rudolfkoenig

Eigentlich ist das nur ein Workaround, weil falls BlockingInformParent nicht aufgerufen wird, FHEM sich trotzdem verklemmt. Da es dir aber hilft, und vermutlich niemanden stoert, habe ich nichts dagegen.

Habs eingecheckt, die "Doku" habe ich ins SVN Kommentar gepackt.

jensb

Hallo Rudi,

danke für die schnelle Rückmeldung. Wenn du es für richtig hältst, werde ich in der Wiki zu "Blocking Call" noch eine Ergänzung zur Methode BlockingInformParent, deren Parameter und zur Verarbeitung des Rückgabewert der $informFn hinzufügen.

Bzgl. des syswrite im Telnet-Modul ist das natürlich ein Workaround, da sich der Patch nur um die andere Seite der Verbindung kümmert. Werde mir das Telnet-Modul noch mal ansehen und prüfen, ob man zumindest in der Methode telnet_Output z.B. vor dem syswrite auf ready-for-write prüfen sollte oder das syswrite mit Timeout aufrufen sollte. Allerdings ist dann die Frage, was man macht, wenn das Schreiben nicht gelingt. Man könnte z.B. einen Fehler-Logeintrag erstellen und die Verbindung trennen.

Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb