Edgewall Software

Ticket #3504: debug_thread_reuse.diff

File debug_thread_reuse.diff, 3.1 KB (added by cboos, 2 years ago)

Some more debugging code to check the "rapid thread id reuse" hypothesis

  • trac/db/pool.py

     
    4646 
    4747    def __del__(self): 
    4848        self.close() 
    49  
    50  
     49        self._pool._debug_decr(self._tid) 
     50                                         
     51         
    5152class ConnectionPool(object): 
    5253    """A very simple connection pool implementation.""" 
    5354 
     
    5960        self._cursize = 0 # current pool size, includes active connections 
    6061        self._connector = connector 
    6162        self._kwargs = kwargs 
     63        self._debug_pcpt = {} 
     64        self._debug_tid = {} 
    6265 
     66    def _debug_decr(self, tid): 
     67        self._available.acquire() 
     68        try: 
     69            pooled_connections_per_thread = self._debug_pcpt.get(tid) 
     70            assert pooled_connections_per_thread # check the debugging code 
     71            assert pooled_connections_per_thread > 0 
     72            self._debug_pcpt[tid] = pooled_connections_per_thread - 1 
     73        finally: 
     74            self._available.release() 
     75 
    6376    def get_cnx(self, timeout=None): 
    6477        start = time.time() 
    6578        self._available.acquire() 
     
    7083                if num == 0: # was pushed back (see _cleanup) 
    7184                    cnx.rollback() 
    7285                self._active[tid][0] = num + 1 
     86                self._debug_pcpt[tid] = self._debug_pcpt.get(tid, 0) + 1 
    7387                return PooledConnection(self, cnx, tid) 
    7488            while True: 
    7589                if self._dormant: 
     
    92106                                                % timeout 
    93107                    else: 
    94108                        self._available.wait() 
     109            if tid in self._debug_pcpt: 
     110                if tid in self._debug_tid: 
     111                    print '[%d] THREAD REUSED (%d)' % \ 
     112                          (tid, self._debug_tid.get(tid)) 
     113                pooled_connections_per_thread = self._debug_pcpt.get(tid) 
     114                assert pooled_connections_per_thread == 0 
     115            self._debug_pcpt[tid] = 1 
    95116            self._active[tid] = [1, cnx] 
    96117            return PooledConnection(self, cnx, tid) 
    97118        finally: 
     
    102123        try: 
    103124            if tid in self._active: 
    104125                num, cnx_ = self._active.get(tid) 
     126                if cnx is not cnx_: 
     127                    print 'ConnectionPool is ', repr(self) 
     128                    print 'In [%d], _active -> %s\n _dormant -> %s' % \ 
     129                          (threading._get_ident(), 
     130                           repr(self._active), repr(self._dormant)) 
     131                    print 'Available connections: %d/%d' % \ 
     132                          (self._cursize, self._maxsize) 
     133                    print 'PooledConnection created from [%d] %s' % \ 
     134                          (tid, repr(cnx)) 
    105135                assert cnx is cnx_ 
    106136                if num > 1: 
    107137                    self._active[tid][0] = num - 1 
     
    131161        try: 
    132162            if tid: 
    133163                cleanup_list = [tid] 
     164                self._debug_tid[tid] = self._debug_tid.get(tid, 0) + 1 
    134165            else: 
    135166                cleanup_list = self._active.keys() 
    136167            for tid in cleanup_list: