Gestorbene Prozesse von Blocking.pm

Begonnen von Markus Bloch, 29 August 2017, 22:13:09

Vorheriges Thema - Nächstes Thema

Markus Bloch

Hallo zusammen.

ich habe unter https://forum.fhem.de/index.php/topic,74214.0.html die Information erhalten, dass bei mehreren Usern PRESENCE offenbar nach dem ersten BlockingCall hängen bleibt und nicht mehr weitermacht. Ursache dabei scheinen tote Prozesse zu sein, welche in BlockingStart() zu einem toten Prozess führen von dem PRESENCE so direkt nichts mitbekommt.

In PRESENCE sieht man in den Internals unter RUNNING_PID den BlockingCall-Rückgabehash in dem unter "pid" der Inhalt  "DEAD:11654" steht. Nach suchen im Code fand ich dies in BlockingStart() in Zeile 139.

Da PRESENCE durch keinen Funktionsaufruf direkte Kenntnis von diesem Zustand erhält, geht es nicht weiter. Ist das so gedacht? Was kann die Ursache für einen toten Prozess sein? Kann man in einem solchen Fall die abortFn aufrufen, damit der Aufrufende Kenntnis davon erhält?

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)

rudolfkoenig

Danke fuer die Meldung, komme leider erst naechste Woche dazu es naeher anzuschauen.

rudolfkoenig

BlockingCall kann man  z.Zt. drei Funktionen mitgeben: die eigentlich aufzurufende Funktion (blockingFn), finishFn um die Ergebnisse im Elternprozess abzuliefern (diese Funktion wird vom Kindprozess via telnet im Elternprozess aufgerufen mit dem Rueckgabewert von blockingFn), und abortFn, wenn die maximale Laufzeit erreicht wurde.

Ich gehe davon aus, dass du auf dem Aufruf von finishFn vergeblich wartest. Das kann ich mir erklaeren, wenn der Kindprozess abgestuerzt ist, oder blockingFn selbst exit aufgerufen hat.

BlockingCall im Elternprozess entdeckt das Problem, weil es regelmaessig alle Kindprozesse mit kill 0 prueft. Ich bin nur unsicher, was man in diesem Fall machen soll: finishFn aufrufen mit "Child exited prematurely" oder eine neue Funktion einfuehren?

CoolTux

@Markus
Ohne jetzt genau geschaut zu haben, aber wäre es möglich das sich in der Rückgabe ein Zeilenumbruch eingeschmuggelt hat. Dann würde die Rückgabe nicht korrekt funktionieren und es würde zu Deinem Phänomen kommen.
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

Markus Bloch

Zitat von: CoolTux am 03 September 2017, 16:57:10
@Markus
Ohne jetzt genau geschaut zu haben, aber wäre es möglich das sich in der Rückgabe ein Zeilenumbruch eingeschmuggelt hat. Dann würde die Rückgabe nicht korrekt funktionieren und es würde zu Deinem Phänomen kommen.

Nein, Line-Breaks werden hier nicht zurückgegeben. Im Falle einer Fehlermeldung werden die Rückgabewerte von bspw. function oder shellscript auf Zeilenumbrüche geprüft und diese durch einen Platzhalterstring ersetzt um diese zu eliminieren.
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

zap

Zitat von: rudolfkoenig am 03 September 2017, 15:57:50
BlockingCall im Elternprozess entdeckt das Problem, weil es regelmaessig alle Kindprozesse mit kill 0 prueft. Ich bin nur unsicher, was man in diesem Fall machen soll: finishFn aufrufen mit "Child exited prematurely" oder eine neue Funktion einfuehren?

Kill 0 ist nicht dazu geeignet festzustellen, ob ein Prozess noch "am Leben" ist. Zitat aus perldoc:

"If SIGNAL is either the number 0 or the string ZERO (or SIGZERO ), no signal is sent to the process, but kill checks whether it's possible to send a signal to it (that means, to be brief, that the process is owned by the same user, or we are the super-user). This is useful to check that a child process is still alive (even if only as a zombie) and hasn't changed its UID"

Es wird also kein Signal an den Child geschickt sondern nur geprüft, ob theoretisch ein Signal geschickt werden könnte.
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

rudolfkoenig

Danke, aber das ist mir seit etwa 30 Jahren bekannt.
Kill 0 ist genau deswegen die uebliche Methode um es festzustellen, ob ein Prozess noch am Leben ist.

zap

Kapiere zwar immer noch nicht, wie du so feststellen willst, ob der Child noch läuft oder im State Zombie/Dead ist, da in beiden Fällen 1 zurück kommt.
Aber egal. Bin vermutlich noch zu unerfahren ;-)
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

rudolfkoenig

fhem.pl setzt $SIG{CHLD} auf IGNORE, damit entstehen keine Zombie Prozesse.

Markus Bloch

Zitat von: rudolfkoenig am 03 September 2017, 15:57:50
BlockingCall im Elternprozess entdeckt das Problem, weil es regelmaessig alle Kindprozesse mit kill 0 prueft. Ich bin nur unsicher, was man in diesem Fall machen soll: finishFn aufrufen mit "Child exited prematurely" oder eine neue Funktion einfuehren?

Ich würde die abortFn aufrufen mit einer entsprechenden Fehlermeldung. Dann weis das Modul, der Aufruf wurde nicht vollständig durchgeführt. Die finishFn soll ja dazu dienen einen abgeschlossenen Call zu reporten.

Nur muss man in diesem Fall sich merken, ob der Call deswegen gestorben ist, weil er bereits beendet und finishFn bereits ausgeführt wurde, oder weil der Prozess tatsächlich gestorben ist.

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)

rudolfkoenig

ZitatIch würde die abortFn aufrufen mit einer entsprechenden Fehlermeldung.
Habs implementiert.

Neu: AbortFn wird mit zwei Argumenten aufgerufen, das zweite Argument ist entweder "Process died prematurely" (falls es "abstuerzt") oder "Timeout: process terminated" (beim Timeout). AbortFn wird bei einer normalen Beendigung nicht aufgerufen.