Modul zur Standardisierung nebenläufiger Prozesse

Begonnen von Dr. Boris Neubert, 24 Februar 2015, 20:40:41

Vorheriges Thema - Nächstes Thema

justme1968

hallo boris,

ja. das schaut jetzt viel besser aus. es blockiert nichts mehr und ich habe nach dem fork zwei prozesse die sauber kommunizieren.

gruss
  andre

ps: ich habe für meine sanbox variante das Log3 in fhem.pl so erweitert das es die pid mit raus schreibt wenn es nicht der haut prozess ist. ich denke das wäre für alle diese auf fork basierten varianten eine gute grundlage.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

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

Dr. Boris Neubert

Danke immi und Andre für Eure Tests!

Andre, ist das Log3 mit Angabe der PID schon Teil des Standards? Bzw. wo ich das?

Viele Grüße
Boris

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

justme1968

es ist nich nicht im standard. eine version ist in meinem sandbox patch.

im prinzip ist es nur beim starten die pid merken und in Log3 die aktuelle pid mit ausgeben wenn sie sich von der gemerkten unterscheidet.

ich weiß nicht ob rudi das einbauen würde.

könntest du dir vorstellen zur kommunikation zwischen den prozessen z.b. json zu verwenden? mit einer art mini protokoll ließe es sich einfacher erweitern und ich könnte dann auch die sandbox darauf aufsetzen.

gruß
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

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

Dr. Boris Neubert

Zitat von: justme1968 am 08 März 2015, 21:42:30
es ist nich nicht im standard. eine version ist in meinem sandbox patch.

Habe ich Tomaten auf den Augen gehabt? Kannst Du bitte die aktuelle Version hier anhängen?

Zitat
könntest du dir vorstellen zur kommunikation zwischen den prozessen z.b. json zu verwenden? mit einer art mini protokoll ließe es sich einfacher erweitern und ich könnte dann auch die sandbox darauf aufsetzen.

Bist Du Telepath? Genau daran habe ich auch gedacht, um standardisiert aus dem Subprocess heraus Readings in den Hauptprozess zu füttern. Idealerweise ein extra Modul für IPC und RPC vermittels JSON.

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

justme1968

die aktuelle version ist (immer noch) hier zu finden: http://forum.fhem.de/index.php/topic,18275.msg173732.html#msg173732.

in der sandbox version hatte ich es so gemacht das die ganz normalen fhem funktionen für readings update zusätzlich an den parent weiter gereicht werden und dort ein setreading auslösen. in der gegenrichtung wird ein attr an das child durchgereicht und dort auch ausgeführt.

das durchreichen sollte dann auch für ReadingVal eingebaut werden so das erst lokal geschaut wird ob es das device gibt, ansonsten im parent.

dadurch können viele module (alle die die standard routinen verwenden und nicht direkt im hash readings oder attribute setzen) ohne weitere änderungen in so eine sandbox gesteckt werden. entweder einzeln oder als gruppe.

den schritt das protokoll sauber zu machen hatte ich zwar schon vor aber noch nicht gemacht.

in dem verlinkten thread ist auch kurz beschrieben das in jeder sandbox ein telnet modul läuft mit dem man sich in die sanbox verbinden kann um zu debuggen.

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

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

Markus Bloch

Hallo zusammen,

ich habe mir mal soeben die eingecheckte Version von SubProcess.pm angeschaut um mal zu schauen, wie ich das in PRESENCE nutzen könnte, nun stellt sich mir gerade ein paar Fragen:

- offenbar kann man aktuell keine Parameter für die onRun-Funktion und die onExit-Funktion setzen. Wie kann ich Argumente übergeben? In einem Modul muss ich ja irgendwo wissen zu welchem Device dieser Aufruf gehört, welche Parameter dafür relevant sind zwecks Zuordnung des Ergebnis.

- Wie kann man ein Funktionsergebnis der onRun-Funktion auswerten?
- Kann man Status-Updates an den Aufrufenden senden?
- In dem Beispiel SubProcessTester ist noch eine Read-Funktion definiert. Wozu ist die genau gedacht?

Danke im Vorraus für ein paar erhellende Worte.

Gruß
Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Dr. Boris Neubert

Hallo Markus,

Zitat von: Markus Bloch am 29 März 2015, 23:15:27
- offenbar kann man aktuell keine Parameter für die onRun-Funktion und die onExit-Funktion setzen. Wie kann ich Argumente übergeben? In einem Modul muss ich ja irgendwo wissen zu welchem Device dieser Aufruf gehört, welche Parameter dafür relevant sind zwecks Zuordnung des Ergebnis.

- Wie kann man ein Funktionsergebnis der onRun-Funktion auswerten?
- Kann man Status-Updates an den Aufrufenden senden?
- In dem Beispiel SubProcessTester ist noch eine Read-Funktion definiert. Wozu ist die genau gedacht?

am besten schaust Du Dir das edukative Beispiel

contrib/SubProcess/98_SubProcessTester.pm

an.

Ich habe gerade eine Version davon eingecheckt, bei der ich beispielhaft eine Variable foobar im subprocess setze und in onRun auswerte,

Die Status-Updates funktionieren über die globale select-Schleife: Du schreibst in der Run-Funktion auf den Parent-Handle und wertest es im Modul in der Read-Funktion aus.

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

Markus Bloch

Ah super vielen Dank, das hilft schonmal ungemein weiter.

Was ich noch vorschlagen würde ist eine Funktion SubProcess_SimpleRead() analog zu DevIo_SimpleRead zu machen, so das man in der ReadFn des Moduls, welches einen SubProcess spawnt mit einem Funktionsaufruf die entsprechenden Daten abrufen kann. Das erspart das ganze gefummel mit select() und ist deutlich intuitiver.

So dass in deinem Beispiel die ReadFn folgendermaßen aussieht:

#####################################
# called from the global loop, when the select for hash->{FD} reports data
sub SubProcessTester_Read($) {

  my ($hash) = @_;
  my $name= $hash->{NAME};
 
  #Debug "$name has data to read!";
 
  my $subprocess= $hash->{fhem}{subprocess};
 
  my $result = SubProcess_SimpleRead($subprocess);

  if(defined($result))
  {
    readingsSingleUpdate($hash, "step", $result, 1);
  } else {
    Log3 $hash, 2, "no data received";
  }
  return $result;
}


Dann denke ich, wäre das ne super Sache.

Vielen Dank.

Gruß
Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

herrmannj

Hi,

in fronthem benutze ich ein ähnliches Konstrukt.

Folgende Erfahrungen:
* nonblocking zum und vom fork. Wenn der irgendwas longrunning macht kann er sonst fhem still legen. Nonblocking read ist mMn nicht ganz optimal in der fhem main select umgesetzt.
* der fork kann sterben ohne das papa das sofort merkt. Folgende write killen den papa wenn er das nicht abfängt.
* wenn non-blocking müssen fork und papa die gegenseitigen Nachrichten auch in chunks verabeiten können (Meint: ein read liefert "Mach mal dies un" .... später "d das"). Braucht festgelegte Nachrichtenformate, trenner.
* Für fronthem habe ich noch Kommandas von papa an fork wie "shutdown" weil sonst "shutdown restart" immer meckert (obwohl es das eigentlich nicht dürfte)

Wieviel davon jetzt für das Nebenlauf-Skelett zum tragen kommt weiß ich nicht - möchte nur meine Erfahrung teilen.

vg
jörg

Dr. Boris Neubert

Hallo Markus,

Zitat von: Markus Bloch am 30 März 2015, 23:35:19
Was ich noch vorschlagen würde ist eine Funktion SubProcess_SimpleRead() analog zu DevIo_SimpleRead zu machen, so das man in der ReadFn des Moduls, welches einen SubProcess spawnt mit einem Funktionsaufruf die entsprechenden Daten abrufen kann. Das erspart das ganze gefummel mit select() und ist deutlich intuitiver.

Danke für Deine Anregung. Ich habe das als subprocess->read() eingebaut. SubProcess.pm und das Beispiel sind aktualisiert und eingecheckt.

Grüße
Boris

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

Dr. Boris Neubert

Hallo Jörg,

Danke für Deine Erfahrungen. Dazu habe ich Fragen und Anmerkungen.

Zitat von: herrmannj am 31 März 2015, 00:29:11
* nonblocking zum und vom fork. Wenn der irgendwas longrunning macht kann er sonst fhem still legen. Nonblocking read ist mMn nicht ganz optimal in der fhem main select umgesetzt.

Ich verstehe nicht, was Du meinst. Wenn der Kindprozess losgetreten ist, blockiert FHEM maximal für die Zeit, welche die ReadFn des verwendenden Moduls benötigt, vom Kindprozess zu lesen, nachdem dieser etwas auf den in der globalen/main select-Schleife überwachten Handle geschrieben hat.
Zitat
* der fork kann sterben ohne das papa das sofort merkt. Folgende write killen den papa wenn er das nicht abfängt.

Im Moment habe ich noch keinen Anwendungsfall, bei dem der Elter aufs Kind schreibt, obwohl das latürnich  :P schon vorgesehen ist. GGf. müsste ich analog zum subprocess->read() ein subprocess->write() bauen, welches vorher das schon existierende subprocess->running() abfragt, ob das Kind noch lebt. Habe dazu eine Notiz in meine lokale Version geschrieben.

Zitat
* wenn non-blocking müssen fork und papa die gegenseitigen Nachrichten auch in chunks verabeiten können (Meint: ein read liefert "Mach mal dies un" .... später "d das"). Braucht festgelegte Nachrichtenformate, trenner.

Stimmt, das ist von der eigentlichen Anwendungslogik des Verwenders abhängig. Im Moment gibt es ja auch Ideen, die Kommunikation zwischen Kind und Elter optional über ein JSON-API zu standardisieren.

Zitat
* Für fronthem habe ich noch Kommandas von papa an fork wie "shutdown" weil sonst "shutdown restart" immer meckert (obwohl es das eigentlich nicht dürfte)

Yep, daran habe ich auch gedacht. Der Verwender muss daran denken (im Beispielmodul realisiert).

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

herrmannj

Hallo Boris

perfekt - Du setzt das in Teilen ja auch anders um.
ZitatIch verstehe nicht, was Du meinst. Wenn der Kindprozess losgetreten ist, blockiert FHEM maximal für die Zeit, welche die ReadFn des verwendenden Moduls benötigt, vom Kindprozess zu lesen, nachdem dieser etwas auf den in der globalen/main select-Schleife überwachten Handle geschrieben hat.
Natürlich. Ich meine die andere Richtung, Parent zum Child. Natürlich unter der Voraussetzung das Parent/Child einen Dialog führen wenn der Prozess losgetreten ist. Wobei Ich mir nicht sicher bin ob das Deiner Intention entspricht.

vg
jörg

Dr. Boris Neubert

Zitat von: herrmannj am 01 April 2015, 22:07:58
Ich meine die andere Richtung, Parent zum Child. Natürlich unter der Voraussetzung das Parent/Child einen Dialog führen wenn der Prozess losgetreten ist. Wobei Ich mir nicht sicher bin ob das Deiner Intention entspricht.

Verstehe. Der Kindprozess hat derzeit keine Möglichkeit, asynchron Botschaften vom Elterprozess zu empfangen. Er müsste also auf den Parent-Handle pollen. während er etwas anderes tut. Wenn das Kind zu lange mit etwas anderem beschäftigt ist, würde dann der Elterprozess (und damit FHEM) tatsächlich blockieren.

Gibt es dafür eine Lösung?

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

justme1968

die lösung (oder zumindest eine lösung) ist im child eine (oder die gleiche) main loop mit select und readFn zu haben wie im normalen (parent) fhem prozess.

hmm.. ich hoffe die vielen klammern machen es nicht undurchsichtiger.

wenn man die idee bis zu ende spinnt landet man wieder bei der sandbox variante bei der in parent und child im prinzip die ganze fhem infrastruktur zur verfügung steht.

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

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

herrmannj

Zitat von: Dr. Boris Neubert am 01 April 2015, 22:21:26
Verstehe. Der Kindprozess hat derzeit keine Möglichkeit, asynchron Botschaften vom Elterprozess zu empfangen. Er müsste also auf den Parent-Handle pollen. während er etwas anderes tut. Wenn das Kind zu lange mit etwas anderem beschäftigt ist, würde dann der Elterprozess (und damit FHEM) tatsächlich blockieren.

Exakt. In fronthem bin ich dazu den Weg gegangen das handle non-blocking aufzusetzen, beim write EWOULDBLOCK abzufragen und einen zusätzlichen Puffer zu pflegen. Das führt dann eben auch dazu das der client nicht davon ausgehen darf bei einem read eine vollständige Botschaft zu empfangen. Es werden dann genau so viele Zeichen geschrieben wie non-blocking möglich und dann gewartet bis der client durch read wieder Platz schafft.

Ob der Weg von Andre das vereinfacht kann ich nicht beurteilen.

vg
jörg