2016-05-06 20 views
0

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.

Antwort

0

Es stellt sich heraus, dass das E-Mail-Paket den Dateideskriptor 4 geschlossen hat, unabhängig davon, ob es ihm gehörte oder nicht. In meinem Fall wurde fd 4 immer der Protokolldatei zugewiesen. Ich verifizierte durch Öffnen einer Textdatei, die fd 4 zugewiesen wurde und schob die Protokolldatei auf fd 5. Die Textdatei fd wurde während der Verarbeitung der ersten E-Mail-Nachricht aus der Mailbox geschlossen.

Der Versuch, das E-Mail-Paket zu debuggen, nahm zu viel Zeit in Anspruch, also schrieb ich einen Ersatz, der für meine Bedürfnisse ausreichte, und machte mich an meine Arbeit.