Исключение в асинхронном доступе к файлу при отключении от демона

Я написал почтовый сервер, используя модули asynchat и mailbox из Python 2.7. При работе в forground все работает нормально и стабильно в течение длительных периодов тестирования. Однако при отсоединении от демона доступ к почтовому ящику вызывает исключение в asyncore.loop() для плохого дескриптора файла. Только доступ к файлу является проблемой. Сокет ввода / вывода продолжает работать просто отлично.

Кажется, не имеет значения, открыт ли файл в __init__() или позже в функции found_terminator().

Я отсоединяю процесс, используя код из рецепта Шредера ActiveState 278731, но использование отдельных модулей демона не меняет симптом.

Вот немного псевдокода, чтобы показать поток:

createDaemon()
s = myServer() # subclass of asynchat.async_chat
dropPermissions #setuid nobody
asyncore.loop()

Вот результат работы strace, когда все взорвется:

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)

Исключенные части включают загрузку модулей parser.py и feedparser.py, которые сами открывают и закрывают несколько файловых дескрипторов, используя mmap2.

Таким образом, fd файла электронной почты закрывается, но вскоре после этого fd появляется в списке выбора. Мне не ясно, как fd добавляется на карту асинхронных каналов или почему он все еще остается после close (). Мне не понятно, какой из ФД сейчас недействителен. Также не ясно, почему этого не происходит при запуске в процессе оболочки.

Если бы я использовал многопоточность, я бы увидел, что это происходит, но я быстро просмотрел импортированные модули и не вижу ничего, что указывало бы на то, что они запускают отдельные потоки или процессы. Кроме того, поведение не изменится, если я продолжу работать от имени пользователя root вместо того, чтобы никого не оставлять.

Конечно, модули asyncore и mailbox используются в других демонах. Я чувствую, что, должно быть, упускаю что-то очевидное.

1 ответ

Оказывается, почтовый пакет закрывал файловый дескриптор 4 независимо от того, принадлежал ли он ему или нет. В моем случае, fd 4 всегда был назначен файлу журнала. Я подтвердил это, открыв текстовый файл, которому был назначен fd 4, и отправил файл журнала на fd 5. Текстовый файл fd был закрыт во время обработки первого сообщения электронной почты, прочитанного из почтового ящика.

Попытка отладки пакета электронной почты заняла слишком много времени, поэтому я написал замену, достаточную для моих нужд, и приступил к работе.

Другие вопросы по тегам