Codievilky August created POOL-391:
--------------------------------------

             Summary: GenericKeyedObjectPool is not thread safe when invoke 
method `borrowObject` and `destroy`  simultaneously
                 Key: POOL-391
                 URL: https://issues.apache.org/jira/browse/POOL-391
             Project: Commons Pool
          Issue Type: Bug
    Affects Versions: 2.9.0, 2.8.0, 2.7.0, 2.6.0, 2.5.0, 2.4.2
            Reporter: Codievilky August


The method `brrowObject` is not thread safe with `destroy` or `clear` method.

The reason is when use GenericKeyedObjectPool#destroy method,it did not ensure 
the *Atomicity* of destroy object from the ObjectDeque。

This may cause in the GenericKeyedObjectPool#borrowObject method,may get the 
wrong number of GenericKeyedObjectPool.ObjectDeque#getCreateCount when need to 
create. And the  GenericKeyedObjectPool#borrowObject will block until timeout.

Here is the sample test code to recur the bug:
{code:java}
// code placeholder
public class CommonPoolMultiThreadTest {
  public static void main(String[] args) {
    GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
    config.setMaxTotalPerKey(1);
    config.setMinIdlePerKey(0);
    config.setMaxIdlePerKey(-1);
    config.setMaxTotal(-1);
    config.setMaxWaitMillis(TimeUnit.SECONDS.toMillis(5));
    GenericKeyedObjectPool<Integer, Integer> testPool = new 
GenericKeyedObjectPool<>(
        new KeyedPooledObjectFactory<Integer, Integer>() {
          @Override
          public PooledObject<Integer> makeObject(Integer key) throws Exception 
{
            System.out.println("start to create");
            return new DefaultPooledObject<>(10);
          }          @Override
          public void destroyObject(Integer key, PooledObject<Integer> p) 
throws Exception {
            System.out.println("start to destroy");
            Thread.sleep(2000);
          }          @Override
          public boolean validateObject(Integer key, PooledObject<Integer> p) {
            return true;
          }          @Override
          public void activateObject(Integer key, PooledObject<Integer> p) 
throws Exception {
            // do nothing
          }          @Override
          public void passivateObject(Integer key, PooledObject<Integer> p) 
throws Exception {
            // do nothing
          }
        }, config
    );
    int borrowKey = 10;
    Thread t = new Thread(() -> {
      try {
        while (true) {
          testPool.borrowObject(borrowKey);
          Thread.sleep(10);
        }
      } catch (Exception e) {
        e.printStackTrace();
        System.exit(1);
      }
    });
    Thread t2 = new Thread(() -> {
      try {
        while (true) {
          testPool.clear(borrowKey);
          Thread.sleep(10);
        }
      } catch (Exception e) {
        e.printStackTrace();
        System.exit(1);
      }
    });
    t.start();
    t2.start();
  }
}

{code}
 



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to