[patch] Blocking.pm braucht waitpid

Begonnen von henryk, 18 März 2014, 14:18:45

Vorheriges Thema - Nächstes Thema

henryk

Moin,

Hin und wieder kommt es ja mal vor, dass bei Benutzung des Blocking-Moduls ein Timeout erreicht wird, und der Kind-Prozess getötet werden muss. Vor allem beim PRESENCE-Modul ist das häufig. Im Log findet man dann zum Beispiel
Timeout for PRESENCE_DoLocalPingScan reached, terminated process 15063
oder
Timeout for PRESENCE_DoLocalFunctionScan reached, terminated process 8862
(dies nur als Kontext für Google :) )

Hier im Forum gab's zum Beispiel schonmal http://forum.fhem.de/index.php?topic=20450.0 mit dieser Symptomatik. Dort hiess es "Weil die Funktion nachwievor noch läuft und irgendwo innerhalb der Funktion hängt (ich tippe auf den Empfangsbefehl des Socket). Und der Prozess kann aufgrund dieser Blockade nicht beendet werden und ist deswegen nun ein Zombie." Diese Erklärung ist falsch. Hintergrund: Zombie-Prozesse sind solche, die bereits beendet worden sind, deren Vater-Prozess aber noch nicht wait()/waitpid(), o.ä. aufgerufen hat, um den Rückgabecode zu erfahren. Das Betriebssystem hält dann noch eine Referenz auf den Prozess vor, falls der Vater dann doch nochmal irgendwann sich dazu bemüßigt, diese Funktion aufzurufen.

Eine Lösung ist also, nach dem kill auch noch ein waitpid zu haben (siehe http://perldoc.perl.org/functions/waitpid.html). Patch dazu hängt an, bitte in FHEM aufnehmen.

--
Henryk Plötz
Grüße aus Berlin

rudolfkoenig

ZitatEine Lösung ist also, nach dem kill auch noch ein waitpid zu haben.
Oder
Zitat$SIG{'CHLD'} = 'IGNORE';
wie das in fhem.pl gesetzt ist. Und:
ZitatWhen a process which has installed signal handlers forks, the child process
  inherits the signals.  All caught signals may be reset to their default action
  by a call to the execve(2) function; ignored signals remain ignored.
MAn ist also fuer Blocking.pm keine Aktion notwendig. Gegenargumente?

henryk

Moin,

ok, du hast Recht, da ist ein $SIG{'CHLD'} = 'IGNORE'; und der Grund warum das bei mir nicht funktionierte (und hin und wieder zu ~32k Zombies führt wonach nichts mehr geht) lag bei mir und nicht in FHEM. Meine Anwesenheitsdetektion benutzt arping und ruft das mit system() auf, um den Rückgabecode erhalten zu können. SIGCHLD IGNORE bricht system(), daher hatte ich ein { local $SIG{CHLD}=''; ... . Mir ist nicht ganz klar, wie, aber das scheint irgendwie Rückwirkungen zu haben. Der Post den ich verlinkt hatte hatte ja ein ähnliches Problem, und hat auch system() verwendet.

Ein waitpid für jedes fork in FHEM wäre quasi defense in depth: Im besten Fall schadet es nichts, im schlimmsten Fall verhindert es Zombies.Zwingend nötig ist es aber wohl doch nicht.

--
Henryk Plötz
Grüße aus Berlin

rudolfkoenig

ZitatSIGCHLD IGNORE bricht system(),

Hast du dazu Details?
Jeder kann in FHEM mit "" system() verwenden, und ich weiss nicht von aktuellen Problemen.

henryk

Moin,

ok, ich hab das zu einfach formuliert: genauer gesagt bricht es den Return-Code von system: http://corp.sonic.net/internals/2008/06/24/perl-sigchld-ignore-system-and-you/. Ich würde aus prinzipiellen Erwägungen nichts anderes verwenden, wenn es um das Ergebnis von Operationen geht (Kommandoausgaben parsen geht eigentlich immer schief), daher war das für mich das gleiche, wie system() zu brechen.

--
Henryk Plötz
Grüße aus Berlin

Markus Bloch

Hallo zusammen,

da in fhem.pl $SIG{'CHLD'} = 'IGNORE'; gesetzt ist, kommt wie von Henryk geschrieben immer bei system() der return code -1.

Dies ist auch der Grund, warum ich keine ping-Checks (o.ä.) mit dem Return Code auswerten kann, sondern aktuell den Output parsen muss.

Mich würde es freuen, wenn dieses IGNORE nicht notwendig währe, damit auch system() wieder funktioniert.

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)

rudolfkoenig

In dem geforkten Prozess kann man natuerlich
$SIG{'CHLD'} = '';
setzen, und danach die Rueckgabewerte von system() auswerten. In dem eigentlichen (parent) FHEM Prozess sollte man das aber lassen, da vermutlich nicht alle Seiteneffekte (wie interrupted system call, etc) korrekt behandelt werden.

Markus Bloch

Hallo Rudi,

währe es nicht besser das direkt in Blocking.pm direkt nach dem Fork durchzuführen, oder sollte das jeder selber setzen?

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

Ich meine, das sollte erstmal jeder selbst setzen, der auf dem return-wert vom select scharf ist. Sonst waeren die aktuellen Benutzer vom Blocking.pm durch irgendwelchen Interrupted-System-Calls ueberrascht, ohne dass sie was gemacht haetten, und das wollen wir nicht.