Python double-fork und Zombie-Prozesse [python2.7] <defunct>

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
e-razor
User
Beiträge: 3
Registriert: Dienstag 16. Oktober 2012, 07:20

Hi Leute,

bin gerade dabei eine Art Prozess-Manager in Python zu schreiben.

Dieser soll ähnlich zu "runit" Ordner auf eine ausführbare Datei "run" überprüfen, starten und falls sie wieder beendet wird erneut starten.

Die Ordnerüberwachung mache ich mit pyinotify - funzt auch soweit ganz gut.

Zum Forken habe ich gelesen, dass man double-fork benutzen sollte, damit man keine Zombie-Prozesse aufgrund des SIGCHILD usw. bekommt. Ich möchte die ausführbare Datei vom eigentlichen Prozess trennen, damit nicht alle Childs beendet werden, wenn der Eltern-Prozess beendet wird. Quasi genau das, was "nohup" macht.

Tjia, hab genau das probiert und bekomme aber eben doch die Zombies.

Kennt sich da jemand aus und hat ein paar Tips für mich?

Ein Beispiel, wie ich forke gibt es hier:
http://pastebin.com/nCqaLJZ1


Besten Dank!
lunar

@e-razor nohup macht etwas anderes. Im Wesentlichen sorgt es nur dafür, dass ein aufgerufenes Kommando SIGHUP ignoriert.

Nutze daemonize anstatt Deine eigene Forking-Routine zu implementieren.
e-razor
User
Beiträge: 3
Registriert: Dienstag 16. Oktober 2012, 07:20

Ahjo... ich möchte halt mit dem selben Prozess mehrere andere starten, die eigenständig laufen.

daemonize macht ja im Grunde nur nen detach vom eigenen Script, also wenn man selber einen Daemon implementieren will.

Finde das daemonize Skript sehr nett, hilft mir nur leider nicht weiter :-(
lunar

@e-razor Du solltest daemonize im Kindprozess verwenden:

Code: Alles auswählen

if os.fork() > 0:
    daemon = daemonize.Daemon()
    daemon.start()
Sprich, Du musst zuerst einen Kindprozess erzeugen, und dann daraus per Doppel-Fork einen Daemon machen, letztlich also dreimal forken.

Ich dachte, dass Beispiel aus Deinem ersten Skript zeigt, wie Du im Kindprozess forkst, um daraus einen Daemon zu machen. Offensichtlich aber benutzt Du das so direkt im Hauptprozess, und ich sehe jetzt auch, dass sich der Vaterprozess nach dem ersten "fork()" im Beispiel gar nicht beendet, weil Du offensichtlich das "os.exit()" entfernt hast (ich gehe davon aus, dass Du den Code nicht selbst geschrieben, sondern irgendwo im Netz gefunden hast).

Dann ist es kein Wunder, dass Du Zombies erhältst. Der doppelte Form funktioniert nur, wenn sich die Vaterprozesse nach beiden Forks beenden. Bleibt der erste Vaterprozess dagegen am Leben, wird er zum Vater des beim zweiten Fork entstehenden Kindprozesses. Der Kindprozess geht nicht wie eigentlich beabsichtigt an init über. Dementsprechend müsste der Vaterprozess "wait()" aufrufen und SIGCHLD abfangen, was er aber in Deinem Beispiel nicht tut, ergo erzeugst Du Zombie-Prozess.

Edit: Statt daemonize nutze besser python-daemon. Der Quelltext von daemonize ist nicht gut, und die Implementierung lässt wichtige Aspekte außer acht. python-daemon scheint dagegen von guter Qualität zu sein, zumindest ist der zugehörige PEP aufschlussreich.
Antworten