Edgewall Software

Ticket #3504: force_close_at_thread_exit.patch

File force_close_at_thread_exit.patch, 2.6 KB (added by cboos, 2 years ago)

Fix for #3504, on top of r3747. The final call to cnx.close() in the request dispatcher forces the disposal of the pysqlite Connection object, even if there are still other PooledConnections waiting to be garbage collected.

  • 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 
     
    3839        ConnectionWrapper.__init__(self, cnx) 
    3940        self._pool = pool 
    4041 
    41     def close(self): 
     42    def close(self, thread_exits=False): 
    4243        if self.cnx: 
    43             self._pool._return_cnx(self.cnx) 
     44            self._pool._return_cnx(self.cnx, thread_exits) 
    4445            self.cnx = None 
    4546 
    4647    def __del__(self): 
     
    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) 
    9395        finally: 
    9496            self._available.release() 
    9597 
    96     def _return_cnx(self, cnx): 
     98    def _return_cnx(self, cnx, thread_exits=False): 
    9799        self._available.acquire() 
    98100        try: 
    99101            tid = threading._get_ident() 
    100102            if tid in self._active: 
    101103                num, cnx_ = self._active.get(tid) 
    102104                assert cnx is cnx_ 
    103                 if num > 1: 
     105                if num > 1 and not thread_exits: 
    104106                    self._active[tid][0] = num - 1 
    105107                else: 
    106108                    del self._active[tid] 
     
    109111                        if cnx.poolable: 
    110112                            self._dormant.append(cnx) 
    111113                        else: 
     114                            cnx.close() 
    112115                            self._cursize -= 1 
    113116                        self._available.notify() 
    114117        finally: 
     
    118121        self._available.acquire() 
    119122        try: 
    120123            for cnx in self._dormant: 
    121                 cnx.cnx.close() 
     124                cnx.cnx.close() ### should be cnx.close() 
    122125        finally: 
    123126            self._available.release() 
  • trac/web/main.py

     
    357357                pass 
    358358            return req._response or [] 
    359359        finally: 
    360             db.close() 
     360            db.close(True) 
    361361 
    362362    except HTTPException, e: 
    363363        env.log.warn(e)