[PATCH]: Blocking.pm

Begonnen von Dirk, 18 März 2013, 21:37:00

Vorheriges Thema - Nächstes Thema

Dirk

Hallo Rudi,

ich habe hier einen Patch für Blocking.pm.
Es gibt hier eine neue Funktion BlockingInformParent()

Der Client kann damit den Parent-Prozess während der Laufzeit vom Child "benachichtigen" und vom Parent Rückgabewerte abfragen. Also nicht erst am Ende von Child Prozess.

Als Parameter erwartet die Sub den aufzurufenden Funktionsnamen und einen zu übergebenen Parameter.
Als Rückgabe wird das entsprechende Return des Funktionsaufrufes an den Child-Prozess gemeldet.

Beispiel:
$value = BlockingInformParent('meineSub', 'Wert');

Magst du dir das einmal ansehen ob das so passt?

Gruß
Dirk



Dirk

Hi Rudi,

ich habe den Patch im vorherigen Posting noch einmal aktualisiert.
Hier war noch ein Bug drin.

Währ schön wenn du dir das noch mal ansehen könntest.

Gruß
Dirk

rudolfkoenig

Habs kurz getestet und eingecheckt.

Vermutung: da man BlockingInformParent jetzt oefters aufrufen kann, sollte man close($client) immer ausfuehren. Kannst Du das bitte pruefen?

Gruss,
  Rudi

Dirk

Ich habe "close($client)" bei mir mal für alle OS aktiviert und werde mal testen.
Wieso was das bisher nur unter WIN aktiv?

Gruß
Dirk

rudolfkoenig

Normlerweise wird implizit ein exit() ausgefuehrt, unter Windows wird fork aber nur emuliert.

Dirk

Na dann mach close hier auch für nicht WIN-Systeme tatsächlich sinn.
Vor allem wenn sehr viele Verbindungen nacheinander vom selben Child-Prozess aus auf gemacht werden.

Ich behalte das hier mal im Auge.

Vielleicht noch ein Paar Worte was ich damit machen will:

Ich arbeite grade wieder an HM485 weiter. Und da gibt es Situationen bei denen ich die Kommunikation mit dem RS485 Adapter in einen Child-Prozess auslagern muss, weil diese teilweise einige Sekunden lang laufen.
Der Child kann zwar über DevIO senden, die Antwort kommt aber immer im Parent-Prozess an. Daher muss der Child hier teilweise recht häufig beim Parent "nachfragen".
Falls du dazu eine bessere Idee hast, lass es mich wissen.

Gruß
Dirk

rudolfkoenig

Du muesstest mir mehr Details nennen, ich muss sonst zu viel Raten. Wenn ich Raten soll :), dann waerst Du ohne threads/forks mit eine Status-Maschine besser dran.

Dirk

Beispiel:
Der so genannte Discovery-Mode scannt den "Bus" nach Geräten. Dabei werden mehrere Nachrichten im ca. 10ms Abstand an alle "Empfänger" geschickt. In Einer Schleife. Die kann dann auch schon man mehrere Sekunden laufen. Ggf. auch im 2-Stelligen Sekunden-Bereich. Das würde dann FHEM so lange Blockieren. Daher der Child Prozess. Zwischen den Nachrichten (wie oben beschrieben) antworten die "Empfänger" wenn sie sich angesprochen fühlen. Diese Antwort kommt aber ausschließlich im Eltern-Prozess an. Daher die Inter-Process-Communication.

Genaue Details zum oben geschriebenen Discovery hab ich in der Protokollbeschreibung Dokumentiert. Abschnitt "Discovery-Nachricht"
Link

Auch die "normale" Kommunikation erwartet bestimmte Timings die ich hier nur mit usleep hinbekomme. Auch das würde den Hauptprozess aus meiner Sicht zu lange blockieren. Daher wird auch hier das Senden und ggf. das Warten auch ACK im Child Prozess ausgeführt.

Reicht dir das als Beschreibung erstmal?

Gruß
Dirk

rudolfkoenig

Das erwaehnte blockiert aber nicht wirklich (man muss ja kein read starten), nur die Antwort kommt spaeter. Ich wuerde es mit eine State-Machine ohne BlockingCall/Kindprozess loesen. Alternativ kann man im Eltern-Prozess FD aus %selectlist entfernen, dann kann das Kind auch selber blockierend lesen.

Dirk

Das Read selber blockiert ja nicht. Ich muss aber z.B. 100ms warten. Und ausreichend genau geht das nur mit usleep. Bei InternalTimer kann ich da nicht sicher sein dass die Timings eingehalten werden. Oder?

Das mit %selectlist ohne FD schau ich mir mal an.
Gib es da ein Bespiel?

Dirk

Ich habe die Beschränkung für WIN bei "close($client)" jetzt raus genommen.
Im Anhang ist das Patchfile dazu.

ZitatAlternativ kann man im Eltern-Prozess FD aus %selectlist entfernen, dann kann das Kind auch selber blockierend lesen.
Könntest du mir hier mal auf die Sprünge helfen.
Ich habe gesucht, und komme zu keiner Antwort was hier zu machen ist, damit ich auch im Childprozess lesen kann.

Gruß
Dirk

rudolfkoenig

Diff eingecheckt.

Zu %selectlist:

DevIO_Open traegt $hash in $selectlist{"$name.$dev"} ein, und DevIO_Close entfernt es.

Wenn Du vor dem BlockingCall $hash aus %selectlist entfernst, dann wird die globale Schleife diesen $hash->{FD} nicht pruefen koennen, und damit dem Kind auch keine Daten "weglesen". Das Kind kann also im Ruhe lesen. Voraussetzung natuerlich, dass nur ein Kind von $hash->{FD} liest. Nach dem das Kind "weg" ist, sollte man %selectlist wieder aktualisieren.

Dirk

So hatte ich das auch verstanden. Wobei man es nach dem BlockingCall löschen muss, sonst erbt der Child ein %selectlist ohne den entsprechenden $hash. Oder hab ich hier ein Denkfehler?

Dennoch denkt der Child nicht daran was zu emfangen. Der Parent natürlich auch nicht mehr. Nach dem wiederherstellen von %selectlist Empfängt der Parent auch wieder schön.

Hast du noch eine Idee?

rudolfkoenig

Beim Kind ist %selectlist irrelevant, da wird ja kein select aufgerufen. Das Kind steckt im BlockingCall, und muss sich selbst um das Lesen kuemmern.

Dirk

Da hast du natürlich recht. Im Child läuft der Main Loop ja nicht.
Da hätte ich ja auch selber drauf kommen können.
Danke dir für den Tipp.