DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17990>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17990

Leaking DB connections - synch problem in GenericKeyedObjectPool.returnObject()

           Summary: Leaking DB connections - synch problem in
                    GenericKeyedObjectPool.returnObject()
           Product: Commons
           Version: Nightly Builds
          Platform: PC
        OS/Version: Windows NT/2K
            Status: NEW
          Severity: Major
          Priority: Other
         Component: Pool
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


I had a problem with "leaking" database connections, using Jdbc2PoolDataSource.
I used both commons-dbcp and commons-pool builds from 10.03.2003.
JDK was 1.3.1_07 and 1.4.1_02 on Windows 2K, Database was Oracle 8.7.1.3 on 
HPUX.

The symptoms are:
- after several minutes of test run value of _totalIdle field keeps increasing 
(as checked with debugger)
- the number of open database connections keeps increasing (as observed on the 
database)

After investigation, I discovered the problem was in 
GenericKeyedObjectPool.returnObject().

I belive the scenario was as follows:
- after evictor removed idle connection, the pool was removed
- then if a test thread wished to return a connection (returnObject()), it had 
to recreate the pool to return the connection to
- unfortunately sometimes the pool was recreated by more than one thread - but 
only one stayed in _poolMap, others were discarded together with the 
connections.

After some changes in synchronization of returnObject(), the problem disapeared.

My version of GenericKeyedObjectPool.returnObject():

    public void returnObject(Object key, Object obj) throws Exception {

        // if we need to validate this object, do so
        boolean success = true; // whether or not this object passed validation
        if((_testOnReturn && !_factory.validateObject(key, obj))) {
            success = false;
            try {
                _factory.destroyObject(key, obj);
            } catch(Exception e) {
                // ignored
            }
        } else {
            try {
                _factory.passivateObject(key, obj);
            } catch(Exception e) {
                success = false;
            }
        }

        boolean shouldDestroy = false;
        synchronized(this) {
            // grab the pool (list) of objects associated with the given key
            CursorableLinkedList pool = (CursorableLinkedList) (_poolMap.get
(key));

            // if it doesn't exist, create it
            if(null == pool) {
                pool = new CursorableLinkedList();
                _poolMap.put(key, pool);
                _poolList.add(key);
            }

            // subtract one from the total and keyed active counts
            _totalActive--;
            Integer active = (Integer) (_activeMap.get(key));
            if(null == active) {
                // do nothing, either null or zero is OK
            } else if(active.intValue() <= 1) {
                _activeMap.remove(key);
            } else {
                _activeMap.put(key, new Integer(active.intValue() - 1));
            }

            // if there's no space in the pool, destroy the object
            // else if we passivated succesfully, return it to the pool
            if(_maxIdle > 0 && (pool.size() >= _maxIdle)) {
                shouldDestroy = true;
            } else if(success) {
                pool.addFirst(new ObjectTimestampPair(obj));
                _totalIdle++;
            }
            notifyAll();
        }
        
        if(shouldDestroy) {
            try {
                _factory.destroyObject(key, obj);
            } catch(Exception e) {
                // ignored?
            }
        }
    }


Please verify this.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to