Issue #877 resolved

Bug in recv wsgiserver

Anonymous created an issue

I've been working with CherryPy for a few months under linux and have seen this maybe two or three times. So it's extremely intermittent.

{{{ File "/home/richardc/projects/market/python/lib/python2.5/site- packages/cherrypy/wsgiserver/init.py", line 968, in communicate req.parse_request() File "/home/richardc/projects/market/python/lib/python2.5/site- packages/cherrypy/wsgiserver/init.py", line 304, in parse_request self._parse_request() File "/home/richardc/projects/market/python/lib/python2.5/site- packages/cherrypy/wsgiserver/init.py", line 317, in _parse_request request_line = self.rfile.readline() File "/home/richardc/projects/market/python/lib/python2.5/site- packages/cherrypy/wsgiserver/init.py", line 212, in readline data = self.rfile.readline(256) File "/home/richardc/projects/market/python/lib/python2.5/site- packages/cherrypy/wsgiserver/init.py", line 822, in readline data = self.recv(self._rbufsize) File "/home/richardc/projects/market/python/lib/python2.5/site- packages/cherrypy/wsgiserver/init.py", line 724, in recv return self._sock.recv(size) error: (4, 'Interrupted system call') }}}

The recv function loops when an exception with an errno in sock_errors_nonblocking is raised:

{{{

!python

def recv(self, size):
    while True:
        try:
            return self._sock.recv(size)
        except socket.error, e:
            if e.args[0] not in socket_errors_nonblocking:
                raise

}}}

However socket_errors_nonblocking does not contain EINTR which my stacktrace shows occurs from time to time.

{{{

!python

socket_errors_nonblocking = plat_specific_errors( 'EAGAIN', 'EWOULDBLOCK', 'WSAEWOULDBLOCK') }}}

sock_errors_nonblocking should probably be initialised as:

{{{

!python

socket_errors_nonblocking = plat_specific_errors( 'EAGAIN', 'EWOULDBLOCK', 'WSAEWOULDBLOCK', 'EINTR', 'WSAEINTR') }}}

Something similar may need to be done for sending data as well.

Reported by RichardC

Comments (8)

  1. Robert Brewer

    wsgiserver already defines:

    socket_error_eintr = plat_specific_errors("EINTR", "WSAEINTR")
    

    We should probably just expand the `except` to pass on those as well.

  2. Log in to comment