(в этом примере я использую модуль pyprocessing , но замена обработки на многопроцессорную работу, вероятно, будет работать, если вы запустите python 2.6 или используете многопроцессорный бэкпорт )
В настоящее время у меня есть программа, которая слушает сокет Unix (используя processing.connection.Listener), принимает соединения и создает поток, обрабатывающий запрос. В определенный момент я хочу изящно завершить процесс, но так как вызов accept () блокирует, и я не вижу способа отменить его хорошим способом. У меня есть один способ, который работает здесь (OS X) по крайней мере, установить обработчик сигнала и сигнализировать процесс из другого потока, например, так:
import processing
from processing.connection import Listener
import threading
import time
import os
import signal
import socket
import errno
# This is actually called by the connection handler.
def closeme():
time.sleep(1)
print 'Closing socket...'
listener.close()
os.kill(processing.currentProcess().getPid(), signal.SIGPIPE)
oldsig = signal.signal(signal.SIGPIPE, lambda s, f: None)
listener = Listener('/tmp/asdf', 'AF_UNIX')
# This is a thread that handles one already accepted connection, left out for brevity
threading.Thread(target=closeme).start()
print 'Accepting...'
try:
listener.accept()
except socket.error, e:
if e.args[0] != errno.EINTR:
raise
# Cleanup here...
print 'Done...'
Единственный другой способ, о котором я подумал, - это проникнуть глубоко в соединение (listener._listener._socket) и установить параметр неблокирования ... но это, вероятно, имеет некоторые побочные эффекты и, как правило, действительно страшно.
Есть ли у кого-нибудь более элегантный (и, возможно, даже правильный!) Способ сделать это? Он должен быть переносимым на OS X, Linux и BSD, но переносимость Windows и т. Д. Не требуется.
Разъяснение :
Спасибо всем! Как обычно, в моем первоначальном вопросе обнаруживаются неясности:)
- Мне нужно выполнить очистку после отмены прослушивания, и я не всегда хочу на самом деле выйти из этого процесса.
- Мне нужно иметь доступ к этому процессу из других процессов, не порожденных тем же родителем, что делает очереди громоздкими
- Причины для потоков:
- Они получают доступ к общему состоянию. На самом деле более или менее распространенная база данных в памяти, так что, я полагаю, это можно сделать по-другому.
- Я должен иметь возможность принимать несколько соединений одновременно, но фактические потоки блокируют что-то большую часть времени. Каждое принятое соединение порождает новый поток; это для того, чтобы не блокировать всех клиентов на операциях ввода / вывода.
Что касается потоков и процессов, я использую потоки для того, чтобы запретить операции блокировки, а процессы для обеспечения многопроцессорности.