fhem.pl client mode default timeout

Begonnen von Sidey, 30 Dezember 2020, 23:49:45

Vorheriges Thema - Nächstes Thema

Sidey

Hi Rudi,

Wenn fhem.pl im Clientmode läuft, dann scheint es keinerlei Timeout Handling zu geben.


Das kann wie folgt reproduziert werden:

1. FHEM in einen blockierten Zustand versetzen:
perl fhem.pl 7072 "{ sleep(100) }" &

2. Anschließend etwas über fhem.pl vom Server abfragen: (Hier als Beispiel die Health check abfrage aus dem Docker Image)
perl fhem.pl 7072 "jsonlist2 TYPE=FHEMWEB:FILTER=TEMPORARY!=1:FILTER=DockerHealthCheck!=0"

Die Antwort bekommt man erst, wenn FHEM nicht mehr blockiert.
Hängt FHEM nun dauerhaft, dann hängt der clientprozess auch dauerhaft.

Als Beispiel liefert z.B. netcat eine Timeout option mit. Wäre es möglich ein Timeoutverhalten auch in den clientmode mit einzubinden?


Der Hintergrund der ganzen Aktion ist, folgender.
Mein FHEM läuft im docker container und es kommt in Verbindung mit devio und ser2net vor, dass mein FHEM in einen blockierten Zustand gerät, sobald die Netzwerkverbindung zu den ser2net definitionen unterbrochen wird.

docker selbst ruft im image dann /health-check.sh auf, welches fhem.pl im clientmode verwendet um Daten von Serverprozess abzufragen.

Das führt dann aber nur dazu, dass ständig neue Instanzen von fhem.pl im Clientmode gestartet werden, das health-check.sh aber nie eine Rückmeldung erhält, dass FHEM nicht reagiert.


fhem        3915  0.0  0.9  90108 72340 ?        S    16:22   0:12 perl fhem.pl fhem.cfg
root        4776  0.0  0.0  14008  2660 pts/0    Ss+  16:23   0:00 /bin/bash
root      183972  0.0  0.0  14008  3024 pts/1    Ss+  18:59   0:00 /bin/bash
root      429248  0.0  0.0  14008  3764 pts/2    Ss   22:37   0:00 /bin/bash
fhem      495619  0.0  0.1  27236 14828 pts/2    S    23:42   0:00 perl fhem.pl 7072 { sleep(100) }
root      495765  0.0  0.0   2384   760 ?        Ss   23:42   0:00 /bin/sh -c /health-check.sh
root      495770  0.0  0.0  13744  3256 ?        S    23:42   0:00 /bin/bash /health-check.sh
root      495774  0.0  0.0  13744  2468 ?        S    23:42   0:00 /bin/bash /health-check.sh
fhem      495775  0.0  0.1  27164 14900 ?        S    23:42   0:00 perl fhem.pl 7072 jsonlist2 TYPE=FHEMWEB:FILTER=TEMPORARY!=1:FILTER=DockerHealthCheck!=0
root      496261  0.0  0.0   2384   696 ?        Ss   23:43   0:00 /bin/sh -c /health-check.sh
root      496266  0.0  0.0  13744  3304 ?        S    23:43   0:00 /bin/bash /health-check.sh
root      496270  0.0  0.0  13744  2528 ?        S    23:43   0:00 /bin/bash /health-check.sh
fhem      496271  0.0  0.1  27136 14992 ?        S    23:43   0:00 perl fhem.pl 7072 jsonlist2 TYPE=FHEMWEB:FILTER=TEMPORARY!=1:FILTER=DockerHealthCheck!=0
root      496737  0.0  0.0   2384   760 ?        Ss   23:43   0:00 /bin/sh -c /health-check.sh
root      496743  0.0  0.0  13744  3312 ?        S    23:43   0:00 /bin/bash /health-check.sh
root      496747  0.0  0.0  13744  2440 ?        S    23:43   0:00 /bin/bash /health-check.sh
fhem      496748  0.2  0.1  27144 14924 ?        S    23:43   0:00 perl fhem.pl 7072 jsonlist2 TYPE=FHEMWEB:FILTER=TEMPORARY!=1:FILTER=DockerHealthCheck!=0
root      497231  0.0  0.0   2384   760 ?        Ss   23:44   0:00 /bin/sh -c /health-check.sh
root      497237  0.0  0.0  13744  3224 ?        S    23:44   0:00 /bin/bash /health-check.sh
root      497241  0.0  0.0  13744  2388 ?        S    23:44   0:00 /bin/bash /health-check.sh
fhem      497242  0.0  0.1  27164 14888 ?        S    23:44   0:00 perl fhem.pl 7072 jsonlist2 TYPE=FHEMWEB:FILTER=TEMPORARY!=1:FILTER=DockerHealthCheck!=0



Grüße Sidey

Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

rudolfkoenig

Bin nicht sicher, ob dein Problem so zu beheben die optimiale Loesung ist.

Wenn ich hier einen Timeout einbaue, dann gibt es bestimmt jemanden, dem das Blockieren egal ist, aber das Ergebnis des Aufrufs nicht.

Alternativen waeren:
- im healthchecker zu pruefen, ob einer bereits laeuft.
- statt fhem.pl nc zu verwenden
- den Status nicht durch "einloggen" in FHEM erfragen, sondern aus FHEM heraus zu "pushen", z.Bsp. regelmaessig eine Datei schreiben.

Bin aber fuer weitere Argumente offen.

Sidey

Hi Rudi,

NC anstelle von fhem.pl verwenden habe ich auch als erstes gedacht.
Da soll es aber in der Vergangenheit Probleme mit Zeichensätzen gegeben haben.

Im health Check prüfen, ob bereits einer läuft habe ich gestern probehalber getestet.
Das löst das Problem, dass unendlich viele Prozesse laufen, aber nicht dass man einen Abbruch vom laufendem Prozess bekommt.

Den Status aus Fhem heraus pushen wäre ein gänzlich anderer Ansatz und würde auch nur bei genau dem bekannten Fall helfen.

Was einen Default timeout angeht, so hat wget beispielsweise einen Default von 900 Sekunden.
Das würde ja prinzipiell auch schon mal helfen.
Ob es wirklich Fälle gibt, in denen jemand 15 Minuten auf eine Antwort wartet kann ich nicht sagen, aber das wäre schon sehr lange.
Bei netcat gibt es eine Option mit der man den Timeout mitgibt.

Ein Default timeout und ein Parameter würden dem fhem Clientmode hier grundsätzlich zugute kommen denke ich.

Gruß Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

rudolfkoenig

ZitatDa soll es aber in der Vergangenheit Probleme mit Zeichensätzen gegeben haben.
Ist jetzt kein starkes Gegenargument, insb. in deinem Fall nicht.

ZitatDas löst das Problem, dass unendlich viele Prozesse laufen, aber nicht dass man einen Abbruch vom laufendem Prozess bekommt.
Verstehe ich nicht: wenn einer bereits laeuft, muss healthcheck halt false liefern.
Laut Internet hat docker selbst fuer healthcheck Prozesse einen timeout von 30 Sekunden und versucht es nur 3-mal, beides konfigurierbar.
Was _genau_ ist das Problem? Wohl kaum, dass die ps Ausgabe laenger wird.

ZitatWas einen Default timeout angeht, so hat wget beispielsweise einen Default von 900 Sekunden.
Das ist mAn zu lang, und ich wuesste gerne, wo es den Unterschied macht.
Wenn ich ein Timeout einbaue, waere der default bei 4-5 Sekunden.

Ich verstehe das Problem nicht, und ich vermute immer noch, dass die vorgeschlagene Loesung nicht die Richtige ist.

Wernieman

Mal eine Grundsätzliche Frage, unabhängig vom Docker:
Bei der Kommunikation Client (fhem.pl) -> FHEM kann es immer zu Problemen kommen. Wenn dann wirklich kein TimeOut definiert ist, wird bis zum "Ende der Welt" gewartet. Währe da nicht eine TinmeOut grundsätzlich sinnvoll (oder über Schalter ein/ausschaltbar)?  Am besten mit Fehlerausgabe.

Die von Dir angegebenen externen Programme können dann reagieren ...

War übrigens "damals" für mich der Grund, mich in tiefer mit nc und fhem einzuarbeiten. Hatte Probleme beim pushen von Daten zu FHEM. Da es System-Daten waren, konnte ich ein Datenverlust verschmerzen, aber kein hängenden Prozess.

Aber das ist nur die Sicht einen Unix-Admins .... und keine Allgemeingültigkeit ...
Habe deshalb auch keinen Patch, sorry
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

rudolfkoenig

Ich will keinen Patch, aber das eigentliche Problem verstehen.
Wenn FHEM klemmt, dann waere mir mit einer timeout Meldung auch nicht geholfen.

Apropos timeout: https://linux.die.net/man/1/timeout

Wernieman

Stimmt .. das ist auch eine Lösung ...
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

Sidey

Zitat von: rudolfkoenig am 31 Dezember 2020, 11:25:05
Ist jetzt kein starkes Gegenargument, insb. in deinem Fall nicht.

Mir war nicht bewusst, dass ich Gegenargumente bringen muss. ;-)

Ich kenne diese Probleme nicht, da ich das health-check script nicht erstellt habe.
Es wurde mir von loredo nur so mitgegeben, dass er von nc auf den fhem clientmode umgestellt hatte, da es Probleme gegeben hat.
Wenn Du der Meinung bist, dass nc besser geeignet ist um fhem Daten an der telnet Schnittstelle zu übergeben dann reiche ich gerne eine PR ein, der das umsetzt.

Soll ich deine Empfehlung denn so verstehen, den fhemclientmode nicht zu verwenden und stattdessen immer netcat?

Zitat von: rudolfkoenig am 31 Dezember 2020, 11:25:05
Verstehe ich nicht: wenn einer bereits laeuft, muss healthcheck halt false liefern.
Laut Internet hat docker selbst fuer healthcheck Prozesse einen timeout von 30 Sekunden und versucht es nur 3-mal, beides konfigurierbar.
Was _genau_ ist das Problem? Wohl kaum, dass die ps Ausgabe laenger wird.

Das kann man so machen. Die drei Zeilen Code habe ich ja bereits getestet.
Das löst aber nur, dass keine weitere Aufrufe des fhemclients erfolgen. Den unendlich hängenden Prozess löst das nicht.
Der Timeout von docker beendet den laufenden Prozess ebenfalls nicht, der setzt den laufenden dockerprozess dann lediglich auf "unhealthy".
Damit docker feststellen kann, ob sich etwas am Status verändert, ruft es weiterhin den health-check auf.

Zitat von: rudolfkoenig am 31 Dezember 2020, 11:25:05
Das ist mAn zu lang, und ich wuesste gerne, wo es den Unterschied macht.
Wenn ich ein Timeout einbaue, waere der default bei 4-5 Sekunden.

Ich verstehe das Problem nicht, und ich vermute immer noch, dass die vorgeschlagene Loesung nicht die Richtige ist.

In meinem Beitrag ging es mir darum, aufzuzeigen, dass der fhemclient Mode keinerlei Timeout kennt und quasi bis in das unendliche wartet.
Das beispiel im docker health-check script war nur ein Beispiel wie sich das auswirkt.
Dass ich dem Aufruf auch eine timeout vorsetzen könnte ist mir durchaus bekannt. Ich bin aber der Meinung, dass der fhemclientmode einen Timeoutparameter vertragen könnten, so wie er in vielen anderen tools auch enthalten ist, die davon abhängig sind, dass eine Gegenstelle reagiert.

Von diesem Timeout würden letztendlich alle profitieren, die diesen clientmode verwenden. Die Lösung, dass jeder der es nutzt sich einen timeout drum herum baut führt doch eher dazu, dass es nicht getan wird, weil da keiner dran denkt und im Normalfall, solange fhem läuft dieser auch nicht benötigt wird.

Eine Timeout aus fhem.pl heraus, hätte halt noch ermöglicht, auf die Ausgabe zu reagieren. Das quasi nachzubauen ist aus meiner Sicht unfug.


Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

rudolfkoenig

Ich vermute zwar weiterhin, dass es hier um Symptom- und nicht Problemloesung geht, aber da ich nicht laenger diskutieren wollte (insb. weil man anfaengt, meine Worte umzudrehen), habe ich vor dem sysread() Aufruf alarm(30) eingebaut, was genau diesen speziellen Fall loest.

Eine bessere Loesung ist mAn das docker Image als (swarm) Service zu starten. Falls FHEM sich verklemmt, startet swarm den Container nach ca 3 Minuten neu, auch mit dem aktuellen /health-check.sh und dem "alten" fhem.pl
Im einfachsten Fall besteht das Starten als swarm Service aus "docker swarm init; docker service create -p8083:8083 fhem/fhem".