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

Changeset 851

Show
Ignore:
Timestamp:
11/28/05 16:36:07
Author:
fumanchu
Message:

Fix for the fix for #311 (onEndRequest method). __del__ cannot work, since it might be called after the thread has already begun processing another request.

Files:

Legend:

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

    r849 r851  
    7575            return 
    7676         
    77         request = cherrypy.server.request(self.client_address, 
    78                                           self.address_string(), "http") 
    79         request.multithread = cherrypy.config.get("server.threadPool") > 1 
    80         request.multiprocess = False 
    81         response = request.run(self.raw_requestline, self._headerlist(), 
    82                                self.rfile) 
    83          
    84         wfile = self.wfile 
    85         wfile.write("%s %s\r\n" % (self.protocol_version, response.status)) 
    86          
    87         has_close_conn = False 
    88         for name, value in response.headers: 
    89             wfile.write("%s: %s\r\n" % (name, value)) 
    90             if name.lower == 'connection' and value.lower == 'close': 
    91                 has_close_conn = True 
    92         if not has_close_conn: 
    93             # This server doesn't support persistent connections yet, so we 
    94             # must add a "Connection: close" header to tell the client that 
    95             # we will close the connection when we're done sending output. 
    96             #  
    97             # From RFC 2616 sec 14.10: 
    98             # HTTP/1.1 defines the "close" connection option for the sender 
    99             # to signal that the connection will be closed after completion 
    100             # of the response. For example, 
    101             #  
    102             #    Connection: close 
    103             #  
    104             # in either the request or the response header fields indicates 
    105             # that the connection SHOULD NOT be considered `persistent' 
    106             # (section 8.1) after the current request/response is complete. 
    107             #  
    108             # HTTP/1.1 applications that do not support persistent connections 
    109             # MUST include the "close" connection option in every message. 
    110             wfile.write("Connection: close\r\n") 
    111          
    112         wfile.write("\r\n") 
    113         try: 
    114             for chunk in response.body: 
     77        request = None 
     78        try: 
     79            request = cherrypy.server.request(self.client_address, 
     80                                              self.address_string(), "http") 
     81            request.multithread = cherrypy.config.get("server.threadPool") > 1 
     82            request.multiprocess = False 
     83            response = request.run(self.raw_requestline, self._headerlist(), 
     84                                   self.rfile) 
     85            s, h, b = response.status, response.headers, response.body 
     86            exc = None 
     87        except (KeyboardInterrupt, SystemExit): 
     88            raise 
     89        except: 
     90            tb = _cputil.formatExc() 
     91            cherrypy.log(tb) 
     92            if not cherrypy.config.get("server.showTracebacks", False): 
     93                tb = "" 
     94            s, h, b = _cputil.bareError(tb) 
     95         
     96        try: 
     97            wfile = self.wfile 
     98            wfile.write("%s %s\r\n" % (self.protocol_version, s)) 
     99             
     100            has_close_conn = False 
     101            for name, value in h: 
     102                wfile.write("%s: %s\r\n" % (name, value)) 
     103                if name.lower == 'connection' and value.lower == 'close': 
     104                    has_close_conn = True 
     105            if not has_close_conn: 
     106                # This server doesn't support persistent connections yet, so we 
     107                # must add a "Connection: close" header to tell the client that 
     108                # we will close the connection when we're done sending output. 
     109                #  
     110                # From RFC 2616 sec 14.10: 
     111                # HTTP/1.1 defines the "close" connection option for the sender 
     112                # to signal that the connection will be closed after completion 
     113                # of the response. For example, 
     114                #  
     115                #    Connection: close 
     116                #  
     117                # in either the request or the response header fields indicates 
     118                # that the connection SHOULD NOT be considered `persistent' 
     119                # (section 8.1) after the current request/response is complete. 
     120                #  
     121                # HTTP/1.1 applications that do not support persistent connections 
     122                # MUST include the "close" connection option in every message. 
     123                wfile.write("Connection: close\r\n") 
     124             
     125            wfile.write("\r\n") 
     126            for chunk in b: 
    115127                wfile.write(chunk) 
    116             request.close() 
     128            if request: 
     129                request.close() 
     130        except (KeyboardInterrupt, SystemExit), ex: 
     131            try: 
     132                if request: 
     133                    request.close() 
     134            except: 
     135                cherrypy.log(_cputil.formatExc()) 
     136            raise ex 
    117137        except: 
     138            tb = _cputil.formatExc() 
     139            try: 
     140                if request: 
     141                    request.close() 
     142            except: 
     143                cherrypy.log(_cputil.formatExc()) 
     144            cherrypy.log(tb) 
    118145            s, h, b = _cputil.bareError() 
     146            # CherryPy test suite expects bareError body to be output, 
     147            # so don't call start_response (which, according to PEP 333, 
     148            # may raise its own error at that point). 
    119149            for chunk in b: 
    120150                wfile.write(chunk) 
  • trunk/cherrypy/_cphttptools.py

    r843 r851  
    3131     
    3232    def close(self): 
    33         self.closed = True 
    34         try: 
    35             applyFilters('onEndRequest') 
    36             cherrypy.serving.request = None 
    37             cherrypy.serving.response = None 
    38         except (KeyboardInterrupt, SystemExit): 
    39             raise 
    40         except: 
    41             cherrypy.log(_cputil.formatExc()) 
    42      
    43     def __del__(self): 
    4433        if not self.closed: 
    45             self.close() 
     34            self.closed = True 
     35            try: 
     36                applyFilters('onEndRequest') 
     37            except (KeyboardInterrupt, SystemExit): 
     38                raise 
     39            except: 
     40                cherrypy.log(_cputil.formatExc()) 
    4641     
    4742    def run(self, requestLine, headers, rfile): 
  • trunk/cherrypy/_cpwsgi.py

    r843 r851  
    9595        if request: 
    9696            request.close() 
    97     except (KeyboardInterrupt, SystemExit): 
    98         raise 
     97    except (KeyboardInterrupt, SystemExit), ex: 
     98        try: 
     99            if request: 
     100                request.close() 
     101        except: 
     102            cherrypy.log(_cputil.formatExc()) 
     103        raise ex 
    99104    except: 
    100105        tb = _cputil.formatExc() 
     106        try: 
     107            if request: 
     108                request.close() 
     109        except: 
     110            cherrypy.log(_cputil.formatExc()) 
    101111        cherrypy.log(tb) 
    102112        s, h, b = _cputil.bareError() 
  • trunk/cherrypy/test/helper.py

    r838 r851  
    8989                self.body.append(chunk) 
    9090            request.close() 
    91         except
     91        except Exception, ex
    9292            if cherrypy.config.get("streamResponse", False): 
     93                try: 
     94                    request.close() 
     95                except: 
     96                    cherrypy.log(cherrypy._cputil.formatExc()) 
    9397                # Pass the error through 
    94                 raise 
     98                raise ex 
    9599             
    96             from cherrypy import _cputil 
    97             s, h, b = _cputil.bareError() 
     100            s, h, b = cherrypy._cputil.bareError() 
    98101            # Don't reset status or headers; we're emulating an error which 
    99102            # occurs after status and headers have been written to the client. 
     
    136139        """ 
    137140         
    138         from cherrypy._cputil import getErrorPage 
    139          
    140141        # This will never contain a traceback: 
    141         page = getErrorPage(status, message=message) 
     142        page = cherrypy._cputil.getErrorPage(status, message=message) 
    142143         
    143144        # First, test the response body without checking the traceback. 
  • trunk/cherrypy/test/test_core.py

    r843 r851  
    328328    def index(self): 
    329329        return "A good piece of cherry pie" 
     330     
     331    def err(self): 
     332        raise ValueError() 
     333     
     334    def errinstream(self): 
     335        raise ValueError() 
     336        yield "confidential" 
    330337 
    331338 
     
    365372        'server.logUnhandledTracebacks': True, 
    366373    }, 
     374    '/cpfilterlist/errinstream': { 
     375        'streamResponse': True, 
     376    }, 
    367377}) 
    368378 
     
    575585        # If this fails, then onEndRequest isn't being called at all. 
    576586        self.assertEqual(_nf.ended, True) 
     587         
     588        ignore = helper.webtest.ignored_exceptions 
     589        ignore.append(ValueError) 
     590        try: 
     591            valerr = '\n    raise ValueError()\nValueError' 
     592            self.getPage("/cpfilterlist/err") 
     593            # If body is "razdrez", then onEndRequest is being called too early. 
     594            self.assertErrorPage(500, pattern=valerr) 
     595            # If this fails, then onEndRequest isn't being called at all. 
     596            self.assertEqual(_nf.ended, True) 
     597             
     598            # If body is "razdrez", then onEndRequest is being called too early. 
     599            if cherrypy.server.httpserver is None: 
     600                self.assertRaises(ValueError, self.getPage, 
     601                                  "/cpfilterlist/errinstream") 
     602            else: 
     603                self.getPage("/cpfilterlist/errinstream") 
     604                # Because this error is raised after the response body has 
     605                # started, the status should not change to an error status. 
     606                self.assertStatus("200 OK") 
     607                self.assertBody("Unrecoverable error in the server.") 
     608            # If this fails, then onEndRequest isn't being called at all. 
     609            self.assertEqual(_nf.ended, True) 
     610        finally: 
     611            ignore.pop() 
    577612     
    578613    def testFlatten(self): 

Hosted by WebFaction

Log in as guest/cpguest to create tickets