Ich habe einen E-Mail-Server mit dem Asynchat und Postfach-Module von Python 2.7 geschrieben. Beim Laufen im Vordergrund funktioniert alles einwandfrei und ist über lange Testzeiten stabil. Wenn er jedoch als Daemon abgehängt wird, verursacht der Zugriff auf das Postfach eine Ausnahme in asyncore.loop() für einen beschädigten Dateideskriptor. Nur der Dateizugriff ist ein Problem. Socket-I/O funktioniert weiterhin einwandfrei.Ausnahme in Asyncore auf Dateizugriff, wenn als Daemon losgelöst
Es spielt keine Rolle, ob die Datei in __init__()
oder später in der Funktion found_terminator() geöffnet wird.
Ich entferne den Prozess mit dem Code von Schroeders ActiveState Rezept 278731, aber die Verwendung separater Daemon-Module ändert das Symptom nicht. Hier
ist ein wenig von Pseudo-Code, den Fluss zu zeigen:
createDaemon()
s = myServer() # subclass of asynchat.async_chat
dropPermissions #setuid nobody
asyncore.loop()
Hier ist der Ausgang, wenn Strace Dinge sprengen:
open("/tmp/MailboxDir/cur/1462562219.M374224P24795Q1.i7", O_RDONLY|O_LARGEFILE) = 8
fstat64(8, {st_mode=S_IFREG|0644, st_size=36, ...}) = 0
...
...
read(8, "To: you\nFrom: me\nSubject: test\n\n"..., 8192) = 36
read(8, "", 4096) = 0
read(8, "", 8192) = 0
close(8) = 0
...
stat64("/tmp/MailboxDir/cur/1462562219.M374224P24795Q1.i7", {st_mode=S_IFREG|0644, st_size=36, ...}) = 0
send(7, "+OK POP3 server ready\r\n", 23, 0) = 23
select(8, [4 5 6 7], [], [4 5 6 7], {30, 0}) = -1 EBADF (Bad file descriptor)
Die elided Abschnitte beinhalten Lade parser.py und feedparser .py Module, die selbst mehrere Dateideskriptoren mit mmap2 öffnen und schließen.
Also die E-Mail-Datei fd ist geschlossen
aber kurz danach, dass fd erscheint in der Auswahlliste. Mir ist nicht klar, wie das fd zur asyncore channel map hinzugefügt wird oder warum es nach dem close immer noch da ist()
. Es ist mir nicht klar, welcher der fd jetzt ungültig ist. Es ist auch nicht klar, warum dies beim Ausführen im Shell-Prozess nicht passiert.
Wenn ich Threading verwende, kann ich dies beobachten, aber ich habe einen kurzen Blick durch die importierten Module geworfen und sehe nichts, um anzuzeigen, dass sie separate Threads oder Prozesse starten. Außerdem ändert sich das Verhalten nicht, wenn ich weiterhin als root laufe, statt auf niemanden zu fallen.
Sicher werden die Asyncore- und Mailbox-Module in anderen Daemons verwendet. Ich fühle mich, als müsste ich etwas Offensichtliches vermissen.