Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to make an exception for broken pipe errors on flask, when the client disconnects prematurely?

Tags:

python

ajax

flask

I'm using flask for development, not production, and i have a view for an ajax request, something like this:

@application.route('/xyz/<var>/', methods=['GET'])
def getAjax(var):
    ...
    return render_template(...)

I'm also using threaded=true for development. Whenever i call that ajax request and then just close the tab that requested it i get an error:

Traceback (most recent call last):   File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 593, in process_request_thread
self.finish_request(request, client_address)   File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)   File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 651, in __init__ 2015-07-07 09:46:09,430 127.0.0.1 - - [07/Jul/2015 09:46:09] "GET /xyz/List/ HTTP/1.1" 200 -
self.finish()   File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 710, in finish
self.wfile.close()   File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 279, in close
self.flush()   File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 303, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size]) error: [Errno 32] Broken pipe

Can i have a try: except block to catch this exception? I tried putting all of the getAjax function's contents on a:

try:
    ...
except socket.error, e:
    logging.warn("socket error " + e)

But it's not working, where should i do this? or how?

EDIT: adding the ajax call

$.ajax({
    type: 'GET',
    url: '/xyz/' + var + '/',
    data: {
            ...
        },
    timeout: 2000,
    success: function(data) {
        ...
        },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        ...
        }
    });
like image 774
tiagosilva Avatar asked Jul 07 '15 09:07

tiagosilva


1 Answers

The problem you have is that by using Flask you're not in control of your full server stack, and so you can't catch errors that arise outside of your application code. The socket.error is actually propagating itself in Flask's built in development server (which might just be a wrapper around SocketServer, I don't know the details), and because it's just a development server not meant for production use, it's not handling the case that a client dies suddenly.

Generally, this shouldn't matter. If you were to actually deploy your code using Gunicorn or something, then the WSGI container would handle the broken pipe without anything from you. You can test this by running your code in such a container locally -- try installing Gunicorn on your computer and seeing what happens when your app code runs in its wrapper.

If you still have a problem, then things might get complicated for you as the problem could be in many different places. Gevent just got to handling this particular error, and so if you're using a lesser-known WSGI container then that might not be able to handle this error either. Or it could be something they're using that can't handle this.

Generally speaking, if you're using a web framework in a standard way, you shouldn't have to handle low level server errors on your own. That's why you're using the web framework to begin with. If you're trying to roll your own video streaming or something, that's another case entirely, but that doesn't seem to be the case here.

like image 97
R Phillip Castagna Avatar answered Sep 26 '22 06:09

R Phillip Castagna