Forkable FHEMWEB Extensions

Begonnen von rudolfkoenig, 12 September 2014, 07:50:59

Vorheriges Thema - Nächstes Thema

Dr. Boris Neubert

Zitat von: justme1968 am 13 September 2014, 12:13:59
das drumherum wäre (konfigurierbar) die bidirektionale komunikation und vor allem das schliessen aller nicht benötigten filedescriptioren so wie es in BlockingCall passiert. alle stellen die fork direkt aufrufen lassen z.b. die verbindungen zu den usb devices und der db offen und verhindern das fhem sich per restart sauber neu starten lässt.

OK.

Zitatden genauen Mechanismus hier zu müssen wir noch festlegen. z.b. über $data{FWEXT}{$url}{FORKABLE} in Verbindung mit einem check auf $$. z.b. so:
$data{FWEXT}{$url}{FORKABLE} = 1 -> fhemweb soll forken, wie für svg

$data{FWEXT}{$url}{FORKABLE} = 2 -> das modul forkt eventuell selber, vor dem aufruf $$ merken, wenn nach dem aufruf die gemerkte pid != $$ ist einfach beenden.

Kurz zwecks Dokumentation und Abgleich/Anregung die derzeit in FHEMWEB implementierte Logik:

  • Die Variable $pid ist definiert, wenn geforkt wurde.
  • Sie enthält 0 im Kindprozess und die PID des Kindprozesses im Hauptprozess.
  • Der Hauptprozess beendet die Verarbeitung nach dem Fork und dem Renice.
  • Der weiterlaufende Teil (Kindprozess oder, falls nicht geforkt wurde, der Hauptprozess) merkt sich $pid in $hash->{PID}
  • Nachdem die Antwort ausgeliefert wird, kommt es in FW_closeConn() zum exit, wenn $hash->{PID} definiert ist, also wenn geforkt wurde und wir im Kindprozess sind.

Das ist hart an der Grenze, was ich noch überblicken kann   :-[ 

Das kann wohl mit zwei, drei Zeilen Kode zu dem von Dir vorgeschlagenen Mechanismus aufgebohrt werden.

Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

rudolfkoenig

Ich habe die Diskussion hier durchgelesen, und ich meine, dass ich nichts unternehmen muss :)
Wenn ich mich irre, korrigiert mich bitte.

Kann sich noch jemand daran erinnern, wieso im BlockingCall die FDs zugemacht werden? Diverse Perl-Module beachten nicht, dass man im Kind die Verbindung nur loswerden moechte, und fuehren zusaetzliche Operationen durch, die im Hauptprozess zu Problemen fuehren koennen.

justme1968

ich glaube ganz ohne kommst du nicht davon :) zumindest einem patch zustimmen und ihn anwenden.


unter anderem deswegen: http://forum.fhem.de/index.php/topic,13156.msg89333.html#msg89333 und deswegen: http://forum.fhem.de/index.php/topic,11852.0.html und noch ein paar anderen solchen problemen dieser art. z.b. mit DbLog.

was meinst du für zusätzliche operationen?

eigentlich gibt es probleme nur dann wenn ein fd nicht zu gemacht wurde und im child drauf zugegriffen wird. wenn alles zugemacht ist kann der child nicht mehr drauf zugreifen.

zu forken ohne die nicht benötigten und beabsichtigen resourcen freizugeben ist falsch. selbst wenn es manchmal funktioniert führt es früher oder später zu ziemlich undurchsichtigen problemen.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Zitateigentlich gibt es probleme nur dann wenn ein fd nicht zu gemacht wurde und im child drauf zugegriffen wird

Dieses Problem sehe ich nicht, da im typischen BlockingCall - Fall nur eine Funktion ausgefuehrt wird. Woran ich mich noch erinnere: Kind laeuft noch, TCP-ServerPort offen, Ursprungs-FHEM kann nicht neu starten. Und irgendetwas gabs auch mit der DB.

Gegen dem close spicht, dass manche Bibliotheken die Parameter der seriellen Leitung beim Close zuruecksetzen, oder beim zumachen einer Verbindung der anderen Seite ein "close" senden, DbLog muss deswegen InactiveDestroy setzen. Ich ueberlege, ob all diese Probleme nicht einfacher dadurch zu loesen sind, dass alle Kind-Prozesse beim Terminieren von FHEM abgeschossen werden.

justme1968

drauf zugreifen war genereller gemeint. Nenn es die resource noch belegen oder offen halten.

nicht nur tcp port. auch alle usb devices die noch offen sind verhindern in diesem fall den neustart.

für kindprozesse lassen sich unter umstaenden nicht immer abschießen weil sie blockierend zum beispiel auf das Netzwerk warten.

und im db fall und eigentlich auch im filelog fall sollte es auch probleme geben wenn das child an einer Stelle aus einem fd liest und der parent gleichzeitig an einer anderen Stelle schreibt. z.b. bei plotfork.

die in kernel file Pointer sind nach dem fork noch geshared.

zumachen aller fd ist wirklich die richtige und saubere lösung.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Dr. Boris Neubert

Hallo Andre,

hast Du eigentlich an dem Thema gearbeitet?

Ich habe heute RSS wieder auf FORKABLE gestellt und setze die Variablen mittels eines über eine Socket-Verbindung zum Elternprozess abgesetztes geheimes set-Kommando. Was für ein Gewürge!

localhost:7072 ist noch hart verdrahtet. Muss ich mir wirklich auch noch ein telnetPort-Gerät suchen, um den tatsächlich verwendeten Port herauszufinden? Hat wohl noch keiner in irgendeinem FHEM-Modul gemacht - oder ich habe Tomaten auf den Augen.

Viele Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

rudolfkoenig

BlockingCall sucht nach telnet Instanzen (und legt Notfalls eins an), leider ist diese Funktionalitaet nicht in eine separate Funktion ausgelagert.

Dr. Boris Neubert

Zitat von: rudolfkoenig am 12 Oktober 2014, 09:14:50
BlockingCall sucht nach telnet Instanzen ...

Danke, das habe ich gesucht. Ich habe ein Snippet daraus nach 02_RSS.pm übernommen.

##################
# Find a telnet device that allows us to connect to the current instance of FHEM we are running under.
sub
RSS_findTelnetDevice() {
    my $telnetDevice= undef;
    foreach my $d (sort keys %defs) {
      my $h = $defs{$d};
      next if(!$h->{TYPE} || $h->{TYPE} ne "telnet" || $h->{SNAME});
      next if($attr{$d}{SSL} || $attr{$d}{password} ||
              AttrVal($d, "allowfrom", "127.0.0.1") ne "127.0.0.1");
      next if($h->{DEF} =~ m/IPV6/);
      $telnetDevice = $d;
      last;
    }
    return $telnetDevice;
   
}


Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

justme1968

hallo boris,

ich bin noch nicht dazu gekommen es so weiter auszubauen wie ich möchte. habe gerade ein modul für die harmon ultimate fernbedienungen am wickel und das hat viel zeit gekostet. ich möchte das thema aber auf weiter verfolgen und hoffe das ich bi sende des jahres so aufgeräumt haben das die einzelnen komponenten auch einzeln wiederverwendbar sind.

für die telnet verbindung schau mal Blocking.pm. da gibt es die funktionalität und es wird auch ein temporäres telnet angelegt wenn es noch keines gibt. vielleicht könnte man das in eine eigene funktion auslagern.

gruss
  andre

edit: hab eben erst gesehen das rudi geantwortet hat und es schon geklärt war.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Dr. Boris Neubert

Hallo,

mir ist es unabsichtlich gelungen, lawinenartig FHEM-Prozesse zu forken. Nicht dass ich wüsste, wie ich das genau zu Wege bringe, und gewollt ist das schon gar nicht  :(

Es hängt mit RSS zusammen, meiner FHEMWEB-Extension, die ich nun wieder auf FORKABLE gesetzt habe. Da geschieht nun also folgendes:

Wenn ein Client http://meinserver:8083/fhem/rss/foo/foo.bar aufruft, erzeugt FHEMWEB einen Kindprozess, der den Request-Handler im RSS-Modul aufruft. Das RSS-Modul liefert als Antwort darauf eine Datei zurück, die vom Kindprozess an den Client ausgeliefert wird. Danach verendet der Kindprozess.

Der von FHEMWEB aufgerufene Request-Handler im RSS-Modul baut die Datei in einigen Sekunden auf. Nach Fertigstellung der Datei beschaffe ich mir über ein Telnet-Gerät den Port, unter dem ich FHEM auf localhost erreiche, und setze auf localhost:port ein set-Kommando ab, um die Buchhaltung des RSS-Geräts im Hauptprozess zu aktualisieren. Anschließend liefere ich die erstellte Datei an FHEMWEB zurück.

Es scheint mir, als ob es dadurch zu einer Parallelisierung der Hauptschleife kommt. Dass also nun auch die Kindprozesse über die wohl offenen duplizierten Dateien beginnen, Datagramme von den verschiedenen Geräten (z.B. CUN) entgegenzunehmen, Hinweis-Mails zu verschicken, Aufrufe von FHEMWEB entgegen zu nehmen. Das führt am Ende zu einer lawinenartigen Vermehrung von FHEM-Prozessen. Bei einer Load von 25 hilft dann nur noch killall -9 perl.

Wenn ich mich während der Lawine per telnet meinServer 7072 verbinde, erhalte ich nach Drücken der Eingabetaste gleich x-mal die Startmeldungen. shutdown wirkt nicht bzw. ich sehe an der kaputten fhem.save, dass gleich mehrere FHEM-Prozesse versuchen, die Datei zu schreiben.

Es liegt daran, dass ich aus dem Kind heraus einen set-Befehl absetze, nicht wahr?

Viele Grüße
Boris

Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

Dr. Boris Neubert

Hallo,

ich hole das Thema nochmal aus der Versenkung.

Ich habe das RSS-Modul auf FORKABLE umgestellt. Die Kommunikation mit dem Elterprozess zum Setzen von Variablen habe ich auskommentiert. Trotzdem kommt es ca. zwei Mal am Tag zu einer Explosion: lawinenartige Vermehrung der fhem-Prozesse plus EOB-Meldungen vom CUN. Irgendwann schlägt der Watchdog bei einer Load von > 25 zu und bootet den Raspberry neu.

Die Ursache könnte sein, dass eine Kombination von Ereignissen, z.B. Kalender- und Wetterabfragen ins Internet die Erzeugung und Auslieferung des Bildes so lange verzögert (> 15 Sekunden), dass bereits der nächste Request kommt, bevor der vorige abgearbeitet ist. Damit sinkt die verbleibende Rechenleistung und es kommen immer mehr Requests, die nicht abgearbeitet werden können. Lawinentod.

Das könnte ich ja mit etwas Grips über Locks abfangen.

Aber die über 200 EOB-Meldungen heute vom CUN machen mir Sorgen. Kann es sein, dass in den Kindprozessen ungewollte Kommunikation mit den anderen Devices stattfindet? Das würde dann nämlich auch die SVG-Erzeugung betreffen, die ja ebenfalls FORKABLE ist.

Viele Grüße
Boris



Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

justme1968

wenn ich es auf die schnelle richtig gesehen habe schliesst fhemweb bei forkable die nicht mehr benötigten descriptoren im gegensatz zu BlockingCall nicht. es hängt also von der logik in dem geforkten prozess ab ob es fälle gibt bei denen die select loop ausgeführt werden kann.

unabhängig davon verhindern die offenen deskriptoren aber auf jeden fall ein sauberes restart.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Dr. Boris Neubert

Zitat von: justme1968 am 02 Dezember 2014, 20:47:17
unabhängig davon verhindern die offenen deskriptoren aber auf jeden fall ein sauberes restart.

Du meinst, shutdown restart startet fhem nicht wieder? Das kann ich bestätigen und das passiert bereits ohne FORKABLE RSS allein mit FORKABLE SVG.

Viele Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

Dr. Boris Neubert

Zitat von: justme1968 am 02 Dezember 2014, 20:47:17
wenn ich es auf die schnelle richtig gesehen habe schliesst fhemweb bei forkable die nicht mehr benötigten descriptoren im gegensatz zu BlockingCall nicht. es hängt also von der logik in dem geforkten prozess ab ob es fälle gibt bei denen die select loop ausgeführt werden kann.

Sollte ich die hier http://forum.fhem.de/index.php/topic,27630.msg222862.html#msg222862 beschriebene Strophe an der Stelle absingen, wo ins geforkte RSS-Modul eingetreten wird?

Viele Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

justme1968

ja. das meine ich. es sollte aber nur passieren wenn solche forakbe prozesse auch gerade laufen. nonblocking OWServer hat leider dieses problem auch noch. ich bin noch nicht dazu gekommen einen patch zu bauen.

das passiert weil fhem beim neustart merkt das der telnetport (durch die children) noch offen ist. das gleiche gilt für alle offenen usb devices.

ein block dieser art (aus BlockingCall) gehört nach jedes fork: 84   # Close all kind of FD. Reasons:
85   # - cannot restart FHEM if child keeps TCP Serverports open
86   # ...?
87   foreach my $d (sort keys %defs) {
88     my $h = $defs{$d};
89     $h->{DBH}->{InactiveDestroy} = 1 if($h->{TYPE} eq 'DbLog');
90     TcpServer_Close($h) if($h->{SERVERSOCKET});
91     if($h->{DeviceName}) {
92       require "$attr{global}{modpath}/FHEM/DevIo.pm";
93       DevIo_CloseDev($h,1);
94     }
95   }


wobei der kommentar nicht stimmt. es geht nicht nur im tcp server ports sondern jeden offenen filedescriptor.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968