Blocking.pm unter Windows

Begonnen von Markus Bloch, 03 Februar 2013, 21:26:23

Vorheriges Thema - Nächstes Thema

Markus Bloch

Hallo zusammen,

ich habe in dem Thread http://forum.fhem.de/index.php?t=msg&goto=62029&rid=117#msg_62029 einen User welcher PRESENCE unter Windows verwendet. Nun ist es so, dass PRESENCE extra das Modul Blocking.pm verwendet um eben keine Verzögerungen von FHEM zu verursachen verwendet. Allerdings scheint sich das unter Windows in Kombination mit einer CUL zu beisen.

Mir ist klar, dass unter Windows direkt kein fork() gibt. Unter ActivePerl macht das aber einen guten Eindruck, nur sobald man forkt und FHEM hat einen CUL geöffnet (oder ein anderes serielles Device) so scheint es zu Fehlermeldungen zu kommen.

Ein FHEM unter Windows alleine nur mit PRESENCE läuft ohne Probleme.

Was kann man da machen?

Viele Grüße

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)

justme1968

ich weiss ja nicht wie es in perl ist aber in c/c++ werden beim fork alle filedescriptoren mit dupliziert. wenn dann aus irgendeinem grund im geformten prozess mit dem gleichen filedescriptor gelesen oder geschrieben wird führt das natürlich zu allen möglichen problemen. deshalb müssen nach einem fork im child alle filedescriptoren geschlossen werden.

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

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

Markus Bloch

Hallo Andre,

ich hab mich da bereits einmal schlau gemacht, da wir auch auf Arbeit sehr intensiv mit Perl und Threading arbeiten.

Unter Windows gibt es kein Fork(). Als Emulation dazu machen Perl Interpreter unter Windows einen Thread dazu auf. Das ist erstmal nicht weiter tragisch. Die File-Descriptoren werden durchaus kopiert, das ist aber erstmal nicht so schlimm. Das Problem ist, dass der Thread mit einem normalen Exit beendet, wodurch auch File-Desctiptoren geflusht werden.

siehe dazu: http://docs.activestate.com/activeperl/5.8/lib/pods/perlfork.html
ZitatOn some operating systems, notably Solaris and Unixware, calling exit() from a child process will flush and close open filehandles in the parent, thereby corrupting the filehandles. On these systems, calling _exit() is suggested instead. _exit() is available in Perl through the POSIX module. Please consult your systems manpages for more information on this.

Daher habe ich einen anderen Weg probiert und versucht den "Windows-Fork" wie einen normalen Perl Thread zu behandeln und am Ende mit

threads->exit();


zu beenden, was auch sehr zuverlässig klappt. Ich kann im Windows Ressourcen Monitor sehen, wie Perl einen Thread anlegt und anschließend wieder beendet. Das Ergebniss wird auch zuverlässig zurückgegeben.

Ich würde die Blocking.pm eh viel lieber Thread-Basiert aufbauen. D.h. ein Thread wird gestartet, arbeitet die Funktion ab und gibt das ganze via Thread::Queue wieder zurück.

Viele Grüße

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)

justme1968

also sind es die filedescriptoren :)

und das nicht noch mehr schief geht ist eher zufall. was z.b. ist wenn wärend so einem blocking call ein funksignal empfangen wird. welcher von beiden prozessen wird es verarbeiten? oder sogar beide? ich denke der einzige saubere weg ist die filedescriptoren zu zu machen.

was die diskussion prozesse oder threads angeht bin ich ein wenig altmodisch. ich denke es gibt nichts was threads koennen das mit prozessen nicht auch möglich ist. das beide sehr große probleme machen können wenn man nicht sehr genau aufpasst. prozesse sind aber klarer voneinander abgeschottet etwas einfacher zu vermitteln.

auf den kleinen plattformen wie fritzbox oder nas systemem ist perl eventuell ohne thread kompiliert und die entscheidung stellt sich eventuell garnicht.

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

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

Markus Bloch

Zitat von: justme1968 schrieb am Di, 05 Februar 2013 08:04das nicht noch mehr schief geht ist eher zufall. was z.b. ist wenn wärend so einem blocking call ein funksignal empfangen wird. welcher von beiden prozessen wird es verarbeiten? oder sogar beide? ich denke der einzige saubere weg ist die filedescriptoren zu zu machen.

Wenn ein Funksignal empfangen wird, werden die Daten über beide Filedeskriptoren bereit gestellt. Da aber der Fork/Windows-Thread damit beschäftigt ist den BlockingCall abzuarbeiten und anschließend sich selber beendet, kommt dieser nie dazu die Daten zu verarbeiten. Der Haupt-Prozess erhält die Daten aber auch und kann diese durch die normalen Verarbeitungszyklen abarbeiten.

Es gehen dabei also keine Daten verloren. Aktuell gehen unter Windows aber Daten verloren, da mittels exit(0); der Thread auch die File-Deskriptoren des Mutterprozesses beendet.

Unter Unix-Systemen ist das kein Problem, da es sich um 2 getrennte Prozesse und daher auch 2 verschiedene File-Deskriptoren handelt. Der Fork wird beendet, ohne den Socket, bzw. irgend welche offenen Dateien zu veränden.

Viele Grüße

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)

justme1968

das ist aber alles nur so lange richtig wie darauf geachtet wird was in dem blocking call wirklich gemacht wird. und das kann sehr schnell durch seitenefekte nicht mehr das sein was man beim flüchtigen darüberschauen erwartet. z.b. kann es durch as dann schief gehen wenn im blocking call etwas mit dem netzwerk gemacht wird. und das wird z.b. auch schon bei der rueckgabe der werte. aber spätestens wenn auf ein langsames geraet per netzwerk und select zugegriffen wird. ich denke das sollte zumindest dokumentiert werden.

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

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

Markus Bloch

Hallo Andre,

hier handelt es sich aber um einen neu erzeugten Socket. Die bestehenden offenen Sockets werden in dem Moment garnicht angefasst.

Viele Grüße

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)