Edgewall Software

Ticket #3504: selective_shutdown_at_thread_exit.patch

File selective_shutdown_at_thread_exit.patch, 4.5 KB (added by cboos, 2 years ago)

Another possible fix for this ticket, still on top of r3747. This solution is a bit more satisfying, as it doesn't require to create a Connection when there's no need to, so an additional benefit of this patch could be a small performance boost.

  • trac/env.py

     
    181181        """Return a database connection from the connection pool.""" 
    182182        return DatabaseManager(self).get_connection() 
    183183 
    184     def shutdown(self): 
     184    def shutdown(self, tid=None): 
    185185        """Close the environment.""" 
    186         DatabaseManager(self).shutdown() 
     186        DatabaseManager(self).shutdown(tid) 
    187187 
    188188    def get_repository(self, authname=None): 
    189189        """Return the version control repository configured for this 
  • trac/db/api.py

     
    7070            self._cnx_pool = ConnectionPool(5, connector, **args) 
    7171        return self._cnx_pool.get_cnx() 
    7272 
    73     def shutdown(self): 
     73    def shutdown(self, tid=None): 
    7474        if self._cnx_pool: 
    75             self._cnx_pool.shutdown() 
     75            self._cnx_pool.shutdown(tid) 
    7676            self._cnx_pool = None 
    7777 
    7878    def _get_connector(self): ### FIXME: Make it public? 
  • trac/db/pool.py

     
    1919except ImportError: 
    2020    import dummy_threading as threading 
    2121    threading._get_ident = lambda: 0 
     22import sys 
    2223import time 
    2324 
    2425from trac.db.util import ConnectionWrapper 
     
    8788                                                'connection within %d seconds' \ 
    8889                                                % timeout 
    8990                    else: 
     91                        print>>sys.stderr, '[%d] wait for connection...' % tid 
    9092                        self._available.wait() 
    9193            self._active[tid] = [1, cnx] 
    9294            return PooledConnection(self, cnx) 
     
    103105                if num > 1: 
    104106                    self._active[tid][0] = num - 1 
    105107                else: 
    106                     del self._active[tid] 
    107                     if cnx not in self._dormant: 
    108                         cnx.rollback() 
    109                         if cnx.poolable: 
    110                             self._dormant.append(cnx) 
    111                         else: 
    112                             self._cursize -= 1 
    113                         self._available.notify() 
     108                    self._cleanup(tid) 
    114109        finally: 
    115110            self._available.release() 
    116111 
    117     def shutdown(self): 
     112    def _cleanup(self, tid): 
     113        # Note: self._available *must* be acquired 
     114        if tid in self._active: 
     115            cnx = self._active.pop(tid)[1] 
     116            if cnx not in self._dormant: 
     117                cnx.rollback() 
     118                if cnx.poolable: 
     119                    self._dormant.append(cnx) 
     120                else: 
     121                    cnx.close() 
     122                    self._cursize -= 1 
     123                self._available.notify() 
     124 
     125    def shutdown(self, tid=None): 
    118126        self._available.acquire() 
    119127        try: 
    120             for cnx in self._dormant: 
    121                 cnx.cnx.close() 
     128            if tid: 
     129                cleanup_list = [tid] 
     130            else: 
     131                cleanup_list = self._active.keys() 
     132            for tid in cleanup_list: 
     133                self._cleanup(tid) 
     134            if not tid: 
     135                for cnx in self._dormant: 
     136                    cnx.close() 
    122137        finally: 
    123138            self._available.release() 
  • trac/web/main.py

     
    228228                        req.display(template, content_type or 'text/html') 
    229229                    else: 
    230230                        self._post_process_request(req) 
     231                except RequestDone: 
     232                    raise 
    231233                except: 
    232234                    err = sys.exc_info() 
    233235                    try: 
     
    348350 
    349351    req = Request(environ, start_response) 
    350352    try: 
    351         db = env.get_db_cnx() 
    352353        try: 
    353354            try: 
    354355                dispatcher = RequestDispatcher(env) 
     
    357358                pass 
    358359            return req._response or [] 
    359360        finally: 
    360             db.close() 
     361            if environ.get('wsgi.multithread', False): 
     362                env.shutdown(threading._get_ident()) 
    361363 
    362364    except HTTPException, e: 
    363365        env.log.warn(e)