_cpcgifs.FieldStorage() can throw a socket timeout error, which isn't handled correctly

Anonymous avatarAnonymous created an issue

Occasionally (more prevalent with HTTP POST requests coming from mobile Browsers with less reliable cellular connectivity), I'm running into a socket timeout error that isn't handled correctly. Here is the stack trace:

Traceback (most recent call last):
  File "cherrypy/_cprequest.py", line 600, in respond
    self.process_body()
  File "cherrypy/_cprequest.py", line 718, in process_body
    keep_blank_values=1)
  File "cherrypy/_cpcgifs.py", line 8, in __init__
    cgi.FieldStorage.__init__(self, *args, **kwds)
  File "python/cgi.py", line 519, in __init__
  File "python/cgi.py", line 640, in read_multi
  File "cherrypy/_cpcgifs.py", line 8, in __init__
    cgi.FieldStorage.__init__(self, *args, **kwds)
  File "python/cgi.py", line 521, in __init__
  File "python/cgi.py", line 655, in read_single
  File "python/cgi.py", line 677, in read_lines
  File "cherrypy/_cpcgifs.py", line 31, in read_lines_to_outerboundary
    line = self.fp.readline(1<<16)
  File "cherrypy/wsgiserver/__init__.py", line 204, in readline
    data = self.rfile.readline(size)
  File "cherrypy/wsgiserver/__init__.py", line 1027, in readline
    data = self.recv(self._rbufsize)
  File "cherrypy/wsgiserver/__init__.py", line 928, in recv
    return self._sock.recv(size)
timeout: timed out

Since this is a benign network connectivity issue, I think CP should gracefully handle the dropped request without logging the stack trace. I'm not sure of the best way to catch this, maybe something like this in _cprequest.py process_body():

        try:
            forms = _cpcgifs.FieldStorage(fp=self.rfile,
                                          headers=h,
                                          # FieldStorage only recognizes POST.
                                          environ={'REQUEST_METHOD': "POST"},
                                          keep_blank_values=1)
+       except socket.error, e:
+           if e.args[0] == 'timed out':
+               raise cherrypy.HTTPError(408)
+           else:
+               raise
        except Exception, e:
            if e.__class__.__name__ == 'MaxSizeExceeded':
                # Post data is too big
                raise cherrypy.HTTPError(413)
            else:
                raise

Matt Bendiksen

Reported by matt_cherrypy@perceptiveautomation

Comments (2)

  1. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.