Cómo detectar ” Canalización rota” en un controlador WSGI

WSGI es extremadamente útil para construir servidores HTTP altamente concurrentes para admitir, por ejemplo, un sondeo largo, sin embargo, en general, el lado del cliente finalizará la solicitud HTTP de larga duración; para limpiar los recursos y abrir los manejadores, se debe notificar al backend del servidor WSGI de tales eventos, sin embargo, actualmente no parece ser posible detectar esos eventos en el controlador WSGI:

# pseudocode example def application(env, start_response): start_response(...) q = Queue() ev_handle = register_event_handler(lambda event, arg: q.put((event, arg))) # ??? need to call eg ev_handle.unregister() when the HTTP request is terminated return iter(lambda: render(q.get()), None) 

Por ejemplo, cuando se usa gevent.pywsgi , la excepción correspondiente ( error: [Errno 32] Broken pipe ) se lanza en algún lugar dentro de gevent y nunca parece salir a la superficie en ningún lugar donde el manejador pueda verlo:

 Traceback (most recent call last): File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/pywsgi.py", line 508, in handle_one_response self.run_application() File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/pywsgi.py", line 495, in run_application self.process_result() File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/pywsgi.py", line 486, in process_result self.write(data) File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/pywsgi.py", line 376, in write self._write(data) File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/pywsgi.py", line 369, in _write self._sendall(data) File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/pywsgi.py", line 355, in _sendall self.socket.sendall(data) File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/socket.py", line 458, in sendall data_sent += self.send(_get_memory(data, data_sent), flags) File "/Users/erik.allik/.virtualenvs/myproj/lib/python2.7/site-packages/gevent/socket.py", line 435, in send return sock.send(data, flags) 

Parece que lo que sucede cuando se termina una solicitud es que, además del rastreo de excepciones (aparentemente no se puede capturar), el iterador que se devolvió desde el controlador WSGI es .close() -d. Por lo tanto, es posible determinar cuándo deben cerrarse los trabajadores / recursos / manejadores asociados con la respuesta. Esto es básicamente lo que hace werkzeug.wsgi.ClosingIterator :

 class ClosingIterator(object): def __init__(self, iterable, on_close): iterator = iter(iterable) self.close = on_close def __iter__(self): return self def __next__(self): return self._next() def application(env, start_response): start_response(...) q = Queue() ev_handle = register_event_handler(lambda event, arg: q.put((event, arg))) return ClosingIterator( iter(lambda: render(q.get()), None), on_close=ev_handle.unregister ) 

Sin embargo, esto no silencia el mensaje de error / rastreo, pero parece tolerable a menos que alguien pueda encontrar una solución que pueda solucionarlo.