BlockingCall: Verständnisprobleme -> Wann wird der Prozess beim Timeout beendet?

Begonnen von mumpitzstuff, 16 Mai 2018, 16:15:07

Vorheriges Thema - Nächstes Thema

mumpitzstuff

Ich habe leider immer noch Probleme den Mechanismus zu verstehen, insbesondere dann, wenn irgend was mal hängen bleibt.

Laut Wiki und auch in den meisten Modulen wird bei einem Timeout im AbortFn lediglich PID gelöscht, ohne den Prozess selbst zu killen, also davor BlockingKill() aufzurufen.

delete($hash->{helper}{RUNNING_PID});

Ich hätte hier eher sowas erwartet:

BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
delete($hash->{helper}{RUNNING_PID});


Wird dadurch ein hängender Prozess wirklich irgendwie beendet? Ich hätte vermutet, das dadurch die Verbindung zum Prozess durchtrennt wird, dieser aber munter weiter rennt. Oder bewirkt hier das Löschen des PID einen impliziten kill des Prozesses? Wenn das nicht passiert, kann es dann dazu kommen, dass auch nach einem Timeout die FinishFn trotzdem noch aufgerufen wird? Wenn der Prozess dann mal ganz hängen sollte, würde der dann für immer am System hängen? Da durch AbortFn $hash->{helper}{RUNNING_PID} schon gelöscht wurde, kann doch auch das BlockingKill in der UndefFn nichts mehr ausrichten.

Was genau bewirkt der Aufruf von BlockingStart() am Ende vom BlockingKill()? Unter bestimmten Bedingungen wird BlockingStart sogar 2x gestartet, einmal über einen Timer und danach noch mal durch einen direkten Aufruf. Wird das nur dazu genutzt irgendwas aufzuräumen oder wird da tatsächlich der Prozess gleich wieder neu aufgesetzt?


rudolfkoenig

AbortFn wird aufgerufen:
- direkt nach dem Start, falls der gestartete Prozess doch nicht laeuft ("Process died prematurely")
- in BlockingKill, nach dem versenden des KILL (-9) Signals ("Timeout: process terminated").
BlockingKill wird aufgerufen, falls timeout spezifiziert ist, und abgelaufen ist. Man kann es aber auch selbst aufrufen, wenn es noetig sein sollte.
Was man im AbortFn macht, ist dem BlockinglRoutinen egal.

mumpitzstuff

Ahh okay. Dann wird beim Ablauf des Timeouts also irgendwo intern bereits BlockingKill aufgerufen und danach erst die AbortFn. Deshalb reicht es dann aus in der AbortFn nur PID zu löschen und man muss BlockingKill an dieser Stelle nicht explizit aufrufen.

Das hat geholfen. Danke!

CoolTux

Alternat kannst Du Dir auch mal SubProcess.pm von Boris anschauen. Ich habe es in meinem aktuellen Modul verwendet und finde es sehr angenehm. Irgendwie besser wie Blocking.pm
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

mumpitzstuff

Danke. Das habe ich mir auch schon angesehen.  ;D Das nutzt aber ebenfalls fork und macht damit prinzipiell erst einmal das Selbe. Der Vorteil liegt dort meines Erachtens in den besseren Kommunikationsmöglichkeiten zwischen Child und Parent.

Ich brauche das aktuell nur grad für einen mini Webserver, der mir Dateien an ein Radio streamt, also relativ unabhängig vom Parent ist. Ich kann hier nur nicht sicherstellen, das sich der Prozeß von selbst beendet bzw. das Ende des Streamings sauber erkannt wird und wollte daher mehr über die Zusammenhänge in Bezug auf BlockingKill in Erfahrung bringen, damit ich da nicht was falsch mache.

Ich könnte aber theoretisch auch den Webserver permanent öffnen, dann könnte sich die Verwendung von SubProcess.pm tatsächlich lohnen. Problem dabei ist eigentlich immer, das FHEM komplett geclont wird (brauche ich in diesem Fall eigentlich gar nicht) und nicht nur ein separater thread erzeugt wird, der nur den Webserver enthält. Muss ich noch mal drüber nachdenken...

zap

Ich habe mich in den letzten Monaten eingehend mit dem Thema Subprozesse und Threads beschäftigt. Threads bringen in Perl keinen Vorteil, da auch hier der komplette Prozess-Speicher geklont wird. Lediglich die Programmierung ist u.a. durch Shared Memory Queues etwas eleganter. Ein großer Nachteil ist, dass es zu Problemem mit Modulen kommt, die JSON verwenden, da dieses nicht Thread safe ist.

Zu Subprocess.pm habe ich selbst einige Verbesserungen beigetragen, um die Parent Child Kommunikation stabiler zu machen. Trotzdem sollte jeder Verwender sowohl im Parent als auch im Child Prozess I/O Pufferung implementieren, da sonst beim Austausch großer Datenmengen Daten verloren gehen können.

Für Deinen Anwendungsfall sollte Subprocess.pm jedoch gut verwendbar sein.

Alternative: Du forkst einen Child. In dem Child ersetzt Du diesen per exec durch ein externes Perl Script mit dem Webserver. Dadurch wird ein Großteil des Speichers aus dem Fork wieder freigegeben.
2xCCU3, Fenster, Rollläden, Themostate, Stromzähler, Steckdosen ...)
Entwicklung: FHEM auf AMD NUC (Ubuntu)
Produktiv inzwischen auf Home Assistant gewechselt.
Maintainer: FULLY, Meteohub, HMCCU, AndroidDB

mumpitzstuff

Das mit dem exec ist ein cooler Trick und hört sich richtig gut an. Danke!