Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1937

Show
Ignore:
Timestamp:
04/03/08 03:07:07
Author:
fumanchu
Message:

Finished the nonblocking fileobject by handling EWOULDBLOCK during recv and accept. Also added experimental code to check SSL pending(), but no verdict yet on whether it's necessary or not.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/wsgiserver/__init__.py

    r1935 r1937  
    117117    return dict.fromkeys(nums).keys() 
    118118 
     119socket_error_eintr = plat_specific_errors("EINTR", "WSAEINTR") 
     120 
    119121socket_errors_to_ignore = plat_specific_errors( 
    120122    "EPIPE", 
     123    "EBADF", "WSAEBADF", 
     124    "ENOTSOCK", "WSAENOTSOCK", 
    121125    "ETIMEDOUT", "WSAETIMEDOUT", 
    122126    "ECONNREFUSED", "WSAECONNREFUSED", 
     
    692696class CP_fileobject(socket._fileobject): 
    693697    """Faux file object attached to a socket object.""" 
    694  
    695     def recv(self, size): 
    696         return self._sock.recv(size) 
    697  
     698     
    698699    def sendall(self, data): 
    699700        """Sendall for non-blocking sockets.""" 
     
    705706                if e.args[0] not in socket_errors_nonblocking: 
    706707                    raise 
    707  
     708     
    708709    def send(self, data): 
    709710        return self._sock.send(data) 
     
    715716            self.sendall(buffer) 
    716717     
     718    def recv(self, size): 
     719        while True: 
     720            try: 
     721                return self._sock.recv(size) 
     722            except socket.error, e: 
     723                if e.args[0] not in socket_errors_nonblocking: 
     724                    raise 
     725     
    717726    def read(self, size=-1): 
    718         data = self._rbuf 
    719727        if size < 0: 
    720728            # Read until EOF 
    721             buffers = [] 
    722             if data: 
    723                 buffers.append(data) 
     729            buffers = [self._rbuf] 
    724730            self._rbuf = "" 
    725731            if self._rbufsize <= 1: 
     
    736742        else: 
    737743            # Read until size bytes or EOF seen, whichever comes first 
     744            data = self._rbuf 
    738745            buf_len = len(data) 
    739746            if buf_len >= size: 
     
    846853            try: 
    847854                return call(*args, **kwargs) 
    848             except (SSL.WantReadError, SSL.WantWriteError)
     855            except SSL.WantReadError
    849856                # Sleep and try again. This is dangerous, because it means 
    850857                # the rest of the stack has no way of differentiating 
    851858                # between a "new handshake" error and "client dropped". 
    852859                # Note this isn't an endless loop: there's a timeout below. 
     860                time.sleep(self.ssl_retry) 
     861            except SSL.WantWriteError: 
    853862                time.sleep(self.ssl_retry) 
    854863            except SSL.SysCallError, e: 
     
    881890 
    882891    def recv(self, *args, **kwargs): 
    883         return self._safe_call(True, super(SSL_fileobject, self).recv, *args, **kwargs) 
    884  
     892        buf = [] 
     893        r = super(SSL_fileobject, self).recv 
     894        while True: 
     895            data = self._safe_call(True, r, *args, **kwargs) 
     896            buf.append(data) 
     897            p = self._sock.pending() 
     898            if not p: 
     899                return "".join(buf) 
     900     
    885901    def sendall(self, *args, **kwargs): 
    886902        return self._safe_call(False, super(SSL_fileobject, self).sendall, *args, **kwargs) 
     
    14061422            return 
    14071423        except socket.error, x: 
    1408             if hasattr(errno, "EINTR") and x.args[0] == errno.EINTR
     1424            if x.args[0] in socket_error_eintr
    14091425                # I *think* this is right. EINTR should occur when a signal 
    14101426                # is received during the accept() call; all docs say retry 
     
    14131429                # elsewhere. See http://www.cherrypy.org/ticket/707. 
    14141430                return 
    1415             msg = x.args[1] 
    1416             if msg in ("Bad file descriptor", "Socket operation on non-socket"): 
    1417                 # Our socket was closed. 
    1418                 return 
    1419             if msg == "Resource temporarily unavailable": 
     1431            if x.args[0] in socket_errors_nonblocking: 
    14201432                # Just try again. See http://www.cherrypy.org/ticket/479. 
    14211433                return 
    1422             if msg == "Software caused connection abort": 
     1434            if x.args[0] in socket_errors_to_ignore: 
     1435                # Our socket was closed. 
    14231436                # See http://www.cherrypy.org/ticket/686. 
    14241437                return 

Hosted by WebFaction

Log in as guest/cpguest to create tickets