FHEM Forum

FHEM - Entwicklung => FHEM Development => Thema gestartet von: dominik am 29 September 2020, 22:21:51

Titel: CoProcess Start bei init_done=0
Beitrag von: dominik am 29 September 2020, 22:21:51
Hallo,

wäre es möglich, dass man einen CoProcess::start() auch während dem Startup (init_done=0) zulässt? Ich habe nämlich Module die im Define den Prozess gestartet benötigen um das Define auszuführen. Wäre super wenn man folgende Zeile entfernen oder als Parameter deaktivieren könnte:
https://github.com/mhop/fhem-mirror/blob/master/fhem/FHEM/CoProcess.pm#L140

Danke & Gruß
dominik
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: zap am 30 September 2020, 11:54:17
Ich denke auch, dass man die Entscheidung dem Entwickler überlassen kann, ob er das vor oder nach Abschluss der FHEM Initialisierung aufruft. Man muss natürlich wissen, was man tut. Ggf. fehlen vor dem init_done = 1 einige Attribute oder Devices, weil die Config noch nicht komplett abgearbeitet wurde.

Das könnte sonst schon zu unangenehmen Seiteneffekten führen.

Alternativ kannst Du natürlich auf CoProcess verzichten und einfach einen fork() nutzen oder z.B. SubProcess.pm verwenden.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: dominik am 30 September 2020, 19:19:31
Da hast du Recht mit den Seiteneffekten, aber das haben wir denke ich so oder so. Bei jedem Define müsste man nämlich in speziellen Fällen auf $init_done prüfen.

Also ich würde mich freuen wenn wir den Start mit einem Parameter forcieren könnten.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: justme1968 am 26 November 2020, 18:24:49
ich verstehe den grund nicht warum der start unbedint im define erfolgen muss und behaupte mal das stimmt nicht.

bei init_done = 0 ist fhem grundsätzlich in einem unfertigen und unbekannten zustand. unter anderem läuft die select loop noch nicht und man kann nicht auf mögliche probleme beim start reagieren. vor dem init_done fehlen definitiv alle attribute, readings und eventuell abhängige devices.

aus fhem heraus niemals direkt fork verwenden. wenn dann dann unbedingt fhemFork verwenden. das sorgt nach bestem wissen dafür das so weit aufgeräumt wird das unter anderem ein neustart möglich ist. beim normalen fork werden ressourcen dupliziert was sehr unangenehme nebeneffekte haben kann. also bitte das direkte fork nicht empfehlen.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: betateilchen am 26 November 2020, 18:37:46
Zitat von: justme1968 am 26 November 2020, 18:24:49
bei init_done = 0 ist fhem grundsätzlich in einem unfertigen und unbekannten zustand. unter anderem läuft die select loop noch nicht und man kann nicht auf mögliche probleme beim start reagieren. vor dem init_done fehlen definitiv alle attribute, readings und eventuell abhängige devices.

Achtung - $init_done ist nicht nur beim FHEM Start relevant.
$init_done wird auch zur Laufzeit von FHEM auf 0 gesetzt, wenn (und solange) ein RereadCfg durchgeführt wird.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: justme1968 am 26 November 2020, 18:45:37
ja. und da ist der zustand unter umständen noch viel unfertiger. nebenbei sind init_done = 0 beim start und init_done=0 beim RereadCfg nicht identisch.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: Wzut am 26 November 2020, 18:50:32
Zitat von: justme1968 am 26 November 2020, 18:45:37
nebenbei sind init_done = 0 beim start und init_done=0 beim RereadCfg nicht identisch.
Gut zu wissen, ich leite daraus für mich ab : !$init_done bekommt in meinen Modulen statt der heutigen Bedeutung "noch nicht" ab sofort die neue "jetzt gerade nicht" 
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: dominik am 26 November 2020, 19:55:30
Folgendes mein Grund warum ich es benötige:

FHEM erwartet, dass gewisse Funktionen / Initialisierungen innerhalb von Define ablaufen. Darunter fällt z.B. setDevAttrList(), das geht nur in Define, danach hat es keine Auswirkung. In meinem Fall benötigt das Define jedoch Zugriff auf den Prozess, der erst mit CoProcess gestartet wird.

Im konkreten Fall geht es um das PythonBinding (https://github.com/dominikkarall/fhem_pythonbinding). Alles was ich sonst in Perl im Define geschrieben habe, schreibe ich jetzt in Python in einem Python Define. Dieses Define kann ich nun aber nicht zum Startup aufrufen, da der CoProcess zuerst gestartet werden muss. Das bedeutet für mich aktuell, dass Python Module erst bei init_done=1 initialisiert werden und nicht davor.
Gerade zur Definition welche Attribute ein Device hat (das weiß nur der Python Code), kann ich daher nicht auf setDevAttrList() zugreifen und muss über userattr gehen. Natürlich ist das auch eine Möglichkeit, aber aus meiner Sicht nicht der schönste Weg, schon alleine deshalb, weil das Python Define nicht innerhalb von init_done=0 ausgeführt wird.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: justme1968 am 26 November 2020, 20:38:39
ohne genau nachgeschaut und nachgedacht zu haben sehe ich nicht warum setDevAttrList nicht auch nach dem define funktionieren sollte. von den beiden modulen die es scheinbar bisher verwendet wird es in einem aus der NotifyFn aufgerufen und ich würde vermuten das es dort funktioniert. was übersehe ich ?

falls setDevAttrList irgendwelche Einschränkungen bezüglich zeitpunkt hat sollte das meiner meinung nach ganz unabhängig von allem anderen behoben werden.

im übrigen wird jedes define das ein anwender interaktiv von hand eingibt bei init_done = 1 durchgeführt und ein modul muss auch damit klar kommen.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: rudolfkoenig am 26 November 2020, 20:39:46
ZitatDarunter fällt z.B. setDevAttrList(), das geht nur in Define, danach hat es keine Auswirkung.
Das ist so nicht richtig: setDevAttrList hat selbstverstaendlich auch nach dem define eine Auswirkung.

Diese Funktion ermoeglicht instanzspezifische Attribute, und die Funktion im define aufzurufen ist natuerlich sinnvoll, da beim Einlesen von fhem.cfg die Attribute direkt nach dem define gesetzt werden. Den gleichen Effekt erreicht man mit dem (ebenfalls instanzspezifischen) userattr Attribut, das ist halt etwas weniger elegant, weil der Benutzer diese Liste sieht und anpassen kann. Eine weitere Alternative ist fuer die Zeit der Initialisierung mit setDevAttrList(".*) alles zu erlauben, und hoffen, dass die fhem.cfg Editierer sich nicht vertippen, und der CoProzess immer und schnell die richtige Liste meldet.

Auf der anderen Seite finde ich es unverantwortlich, einen Prozess zu starten, der FHEM blockiert, nur damit man keine Daten in FHEM speichern muss. In diesem Fall hat man auch keinen Support vom FHEM Framework, da dieser vom globalen select abhaengt, d.h. man darf die Finger schmutzig machen mit allen Details der Kommunikation.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: justme1968 am 26 November 2020, 20:40:28
ok. ich habe gerade den betreffenden thread gefunden. das problem ist nicht das setDevAttrList nicht später aufgerufen werden kann sondern das bevor es gesetzt ist die attribute eventuell nicht bekannt sind und nicht wieder hergestellt werden.

ich denke zuerst alles erlauben und später einschränken ist hier die richtige lösung.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: dominik am 26 November 2020, 21:08:31
Ok, sorry, ihr habt Recht, die Fehlersituation ergab sich aufgrund der nach dem Define nicht vorhandenen Attribute und somit wurden die in fhem.cfg gespeicherten Werte nach dem Start nicht übernommen.
Alle möglichen Attribute per Default setzen geht leider nicht, da auch diese Menge erst nach dem Start des Python Servers vorhanden ist.

ZitatEine weitere Alternative ist fuer die Zeit der Initialisierung mit setDevAttrList(".*) alles zu erlauben, und hoffen, dass die fhem.cfg Editierer sich nicht vertippen, und der CoProzess immer und schnell die richtige Liste meldet.
Ah, ich wusste nicht, dass man bei setDevAttrList auch Wildcards verwenden kann. Das wäre natürlich die Lösung! Danke!

ZitatAuf der anderen Seite finde ich es unverantwortlich, einen Prozess zu starten, der FHEM blockiert, nur damit man keine Daten in FHEM speichern muss. In diesem Fall hat man auch keinen Support vom FHEM Framework, da dieser vom globalen select abhaengt, d.h. man darf die Finger schmutzig machen mit allen Details der Kommunikation.
Was meinst du mit blockieren? Der CoProcess blockiert FHEM nicht, genau so wenig blockiert der Python Code FHEM. Ich musste nur einen Teil "blockierend" machen, nämlich die Funktionsaufrufe der Python DefineFn, AttrFn, usw. da die FHEM Funktionen im Standard auch direkt in der Perl FHEM Mainloop abgewickelt werden und somit "blockieren". Die Daten speicher ich bereits alle in FHEM, in Python werden diese nur zur Laufzeit verarbeitet.

//Edit: quote Tags korrigiert
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: betateilchen am 26 November 2020, 21:14:26
kannst Du Deinen letzten Beitrag bitte lesbar gestalten? Danke.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: rudolfkoenig am 26 November 2020, 21:16:51
ZitatWas meinst du mit blockieren?
Da du geschrieben hast, das du den "vorzeitigen" CoProzess wegen setDevAttrList benoetigst, habe ich angenommen, dass im define der zweite Prozess gestartet werden soll, und solange gewartet (d.h. FHEM blockiert) wird, bis die Antwort vom zweiten Prozess eintrifft, und setDevAttrList mit dem richtigen Wert aufgerufen werden kann.
Titel: Antw:CoProcess Start bei init_done=0
Beitrag von: dominik am 26 November 2020, 21:32:20
Das ist ein separates Modul welches den CoProcess startet. Aber du hast Recht, das CoProcess Modul (10_PythonBinding.pm) muss vor den eigentlichen Modulen (10_PythonModule.pm) initialisiert werden...und sogar dann kann es sein, dass der Start 2-3s dauert und es kurzzeitig zu einem Blocking kommt wenn der CoProcess noch nicht fertig gestartet hat.
Schön wären asynchrone FHEM Define, Attr, ... Funktionen :)

Also wenn setDevAttrList(".*") funktioniert, kann das Thema als erledigt betracht werden. Außerdem würde es, wie Rudi richtig festgestellt hat, trotzdem noch zum Blockieren kommen, da ich nicht garantieren kann, dass ein Modul 100% fertig geladen (CoProcess gestartet) ist bevor weitere Module initialisiert werden. Das ginge vermutlich nur mit async/await ohne blockieren.