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.
ich habe folgendes Problem, ich habe eine Funktion die die ganze Zeit einen Ordner beobachtet. Sobald etwas passiert wird ein fork ausgeführt und im Kindprozess der Rest abgearbeitet. während der Elternprozess weiter beobachtet. Das Problem hierbei ist, das die Kindprozesse immer als Zombies enden und ich diese nicht weg bekomme. Auch ein double fork bringt mich nicht weiter. Momenetan sieht es ungefähr so aus
Es gibt doch schon fertige Pakete dafuer. daemonize oder so. Und warum muss denn daemonisiert werden, wenn du eh immer neue Prozesse startest? Da reicht doch ein simples subprocess, bzw. warum reicht das nicht?
Also in dem Kindprozess werden Dokumente an den Drucker gesendet , log Einträge erstellt, Mails versendet usw. Ich weiß nicht ob ich das mit einem subprocess so hin bekomme. Ich stehe aber auch ehrlich gesagt gerade komplett auf dem Schlauch, ich habe schon so viele Varianten jetzt versucht aber die Kindprozesse enden immer als Zombies.
@__deets__: mit subprocess hast Du das selbe Problem mit den Zombies.
@Mazar: die Aufgaben hören sich auch eher danach an, als ob ein eigenes Programm der richtige Weg wäre.
Die Lösung des Zombieproblems ist es, in regelmäßigen Abständen zu schauen, ob die Kindprozesse inzwischen beendet sind. Das ist ja bei einer Dauerschleife, die auf Verzeichnisänderungen wartet, kein Problem. Auf diese Weise kann man auch prüfen, ob es im Kindprozess irgendwelche Fehler gab und dann entsprechend darauf reagieren.
Also ich habe jetzt folgende Struktur
parent
child
grandchild
Ich bekomme jetzt auch das 2 fork welches die Logik ausführt komplett gelöscht habe aber nun weiter das Problem mit dem ersten child das dieses nun zu einem Zombie wird, also im Endeffekt das Gleiche. Selbst wenn ich das erste child ewig warten lasse und es kille während es läuft, wird es zu einem Zombie :/
Kleine Anmerkung, evtl gibt es dadurch ganz andere Lösungsansätze: Mir ist es nicht wichtig einen daemon zu erstellen sondern es ist mir wichtig einen neuen Prozess zu erzeugen der unabhängig vom parent läuft damit dieser weiter das Verzeichnis beobachten kann.
@Sirius3: wieso habe ich mit subprocess das gleiche Problem? Da brauche ich ja ueberhaupt keinne Fork mehr, und subprocess kann "wait". Explizit oder implizit, wie der User es will.
class MyHandler(FileSystemEventHandler):
def on_created(self, event):
if not event.is_directory:
subprocess.call(["mein-kommando", event.path ]) # nur skizziert
@__deets__: Aber das blockiert doch jetzt solange mein-kommando läuft. Wenn man dagegen `Popen` nimmt, muss man irgendwo ein `wait()` machen. Da ist dann die Frage wo man das einbaut bei was auch immer der OP hier verwendet.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
@__deets__: Du brauchst kein fork mehr, weil das subprocess für Dich macht.
@Mazar: wie sieht Dein jetziger Code denn aus? Und wie schon geschrieben, kann es sehr nützlich sein, sich die Prozess-IDs zu merken und regelmäßig zu pollen.
class MyHandler(FileSystemEventHandler):
def on_created(self, event):
if not event.is_directory:
newpid = os.fork()
if newpid == 0:
os.setsid()
newpid = os.fork()
if newpid == 0:
filepath, filename = os.path.split(event.src_path)
child(filename)
os._exit(0)
else:
os._exit(0)
else:
os.waitpid(newpid, 0)
So klappt es ganz gut. Der größte Fehler lag wohl daran das ich niergends wait genutzt hatte und durch 2 forks wird aauch der Elternprozess nicht blockiert.
__blackjack__ hat geschrieben: Dienstag 31. Juli 2018, 14:34
@__deets__: Aber das blockiert doch jetzt solange mein-kommando läuft. Wenn man dagegen `Popen` nimmt, muss man irgendwo ein `wait()` machen. Da ist dann die Frage wo man das einbaut bei was auch immer der OP hier verwendet.
Voellig richtig, aber genau der Code der nach dem fork warten muss, muss dann halt auf einen Sack Popens warten. Wo ist da der Unterschied? Und bei subprocess kann man sich halt nicht verheddern.
@__deets__: Bei dem double fork muss man doch nur kurz warten bis der geforkte Prozess seinerseits geforked hat und sich beendet. Das blockiert ja nur ganz kurz. Und der dann noch laufende Prozess hat keinen Elternprozess mehr und wird deshalb von init ”adoptiert” → wird nicht zum Zombie.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Das ist sicher richtig, nur entstehen Zombies ja nur, wenn der Parent-Prozess noch lebt, aber nicht wartet. Wenn der also eine Liste von Kind-Prozessen verwaltet & dann "bewartet", dann ist alles gut. Und falls der Parent stirbt, erledigt der init das. Wie du ja selbst sagst. Es ist halt die Frage, ob man den semantisch immer ein bisschen ueberraschenden fork-Call einfuehrt, oder einen Mechanismus zum wait-aufruf via timer etc. Unixiger ist allerdings das fork, insofern: schoenere Loesung
Wenn es den Use-Case hier unterstuetzt, das hab' ich nicht geprueft. Aber damit sollte dann ein externer Prozess ueber subprocess zB ja ebenfalls schnell zurueckkehren Da ist dann die Frage, welchen Zustand der Worker-Prozess alles braucht. Allerdings bin ich da eh eher fuer explizit statt implizit irgendwechen Prozesszustand anzunehmen, der nach dem geforke noch rumliegt...