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)