51 votes

Django Broken pipe en mode Debug

J'ai django 1.3 sur le serveur distant derrière Nginx.

Si je lance django avec apache + mod_wsgi, je peux regarder les erreurs dans les fichiers de log d'apache. C'est ok, mais j'aimerais avoir dans la console.

Si je lance django propre serveur de développement, j'ai des erreurs avec stacktrace en console uniquement lorsque DEBUG = False. En mode DEBUG console sorties

Exception happened during processing of request from (..., ...)
Traceback (most recent call last):
  File "/usr/local/python/lib/python2.7/SocketServer.py", line 284, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/local/python/lib/python2.7/SocketServer.py", line 310, in process_request
    self.finish_request(request, client_address)
  File "/usr/local/python/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/python/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 570, in __init__
    BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
  File "/usr/local/python/lib/python2.7/SocketServer.py", line 641, in __init__
    self.finish()
  File "/usr/local/python/lib/python2.7/SocketServer.py", line 694, in finish
    self.wfile.flush()
  File "/usr/local/python/lib/python2.7/socket.py", line 301, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe

Je veux comprendre pourquoi? Pourquoi django juste sortie sans nom d'Exception? Pourquoi est-il dépendent de la variable DEBUG.

Cette erreur se produit surtout des vues sur l'extérieur quand je n'ai pas accès à l'objet de demande. Donc, je ne peux pas l'attraper dans l'intergiciel (middleware ou de l'utilisation de la journalisation de gestionnaire.

La mise à JOUR. J'ai remarqué que si je demande à django directement le serveur je n'ai jamais Cassé la pipe. Donc, la question peut se produire alors que proxy Nginx django?

62voto

jro Points 5538

Ce n'est pas vraiment un problème avec votre site, de plus avec le Django devserver: voir Django billet. Pour dire les choses crûment, juste l'ignorer car c'est une erreur connue, et ne sera pas corrigé.

Dans ce billet, les commentaires d'une explication est donnée:

Selon plusieurs sources, le "Broken Pipe" est un navigateur caprice. Par exemple, le navigateur lit à partir de la prise de courant et décide alors que l'image de ce qu'il lit, apparemment, n'a pas changé. Le navigateur maintenant, c' (de force) ferme la connexion, car il n'a pas besoin de plus de données. L'autre extrémité de cette prise (le python runserver) nous pose un socket exception d'indiquer au programme que le client a Cassé le support pipe".

8voto

San4ez Points 4184

Nginx directive proxy_intercept_errors off; (désactivé par défaut) est ce dont j'avais besoin

6voto

Rick Mohr Points 478

La nginx directive (cocher la réponse) ne fonctionne pas pour moi, mais la combinaison de singe de patchs de Igor Katson et Michael_Scharf n':

def patch_broken_pipe_error():
    """Monkey Patch BaseServer.handle_error to not write
    a stacktrace to stderr on broken pipe.
    http://stackoverflow.com/a/22618740/362702"""
    import sys
    from SocketServer import BaseServer
    from wsgiref import handlers

    handle_error = BaseServer.handle_error
    log_exception = handlers.BaseHandler.log_exception

    def is_broken_pipe_error():
        type, err, tb = sys.exc_info()
        return repr(err) == "error(32, 'Broken pipe')"

    def my_handle_error(self, request, client_address):
        if not is_broken_pipe_error():
            handle_error(self, request, client_address)

    def my_log_exception(self, exc_info):
        if not is_broken_pipe_error():
            log_exception(self, exc_info)

    BaseServer.handle_error = my_handle_error
    handlers.BaseHandler.log_exception = my_log_exception

patch_broken_pipe_error()

4voto

Michael_Scharf Points 792

Ici est une façon de prévenir les pour imprimer le message sur stderr. Juste monkey patch le BaseServer.handle_error fonction. C'est comment je le fais:

def patch_broken_pipe_error():
    """Monkey Patch BaseServer.handle_error to not write
    a stacktrace to stderr on broken pipe.
    http://stackoverflow.com/a/7913160"""
    import sys
    from SocketServer import BaseServer

    handle_error = BaseServer.handle_error

    def my_handle_error(self, request, client_address):
        type, err, tb = sys.exc_info()
        # there might be better ways to detect the specific erro
        if repr(err) == "error(32, 'Broken pipe')":
            # you may ignore it...
            logging.getLogger('mylog').warn(err)
        else:
            handle_error(self, request, client_address)

    BaseServer.handle_error = my_handle_error


patch_broken_pipe_error()

2voto

rane Points 79

J'ai été en mesure de se débarrasser de ce par

proxy_buffering off;

Cela les empêche de tampon de réponse de serveur mandaté. Cela conduit à d'autres problèmes de back-end de l'application verrouillée pendant longtemps si le client est sur une connexion extrêmement lente.

Le conditionner pour les demandes particulières, utiliser X-Accel-mise en mémoire Tampon=pas dans l'en-tête de réponse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X