8

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) {
        ...
        }
    });
tiagosilva
  • 1,695
  • 17
  • 31
  • Have you checked [this answer](http://stackoverflow.com/questions/22560259/error-errno-32-broken-pipe)? And consider to post your Ajax code if you want more feedback. – doru Jul 07 '15 at 11:06
  • Well the selected answer doesn't seem to give me any more information, since i already know that the error is caused by the client being being absent to receive the answer. But i'm not sure what the poster meant with the edit: saying he didn't sent back the response from Python. – tiagosilva Jul 07 '15 at 11:18
  • Have you tried to increase the `timeout` to 20000 for example? – doru Jul 07 '15 at 11:22
  • yes, i usually call it with 12000, and i've tried higher values, but this isn't about a timeout, textStatus is not timeout, nor would it make much sense increasing the timeout if the problem is that the client closes the socket... also i'm not trying to avoid the error, im trying to deal with it – tiagosilva Jul 07 '15 at 13:09

1 Answers1

5

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.

  • Thanks, i'm actually running the code in production behind gunicorn, when the same thing happens in production there isn't an error per say. The error part of the ajax call still gets called but {textStatus} is 'error', {errorThrown} is empty. From what you say i get the idea that this shouldn't happen. Am i correct in assuming that? – tiagosilva Jul 20 '15 at 11:06
  • Well the server error definitely shouldn't be happening, and it's good that it isn't. I'm surprised the Javascript code is hanging around long enough to run the error handling code if you're closing the tab/navigating away, though. It could be just a part of the bail out for the function call. I would try it with different browsers and see if you get the same behavior. If nothing is being negatively affected, though, I probably wouldn't worry about a browser side error during exit. – R Phillip Castagna Jul 20 '15 at 14:55