[ https://issues.apache.org/jira/browse/POOL-419?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17923370#comment-17923370 ]
Raju Gupta edited comment on POOL-419 at 2/3/25 11:12 PM: ---------------------------------------------------------- Hi [~ggregory]. Hope you are well. I really thought about your comment last year to focus on bug fixes. I have tried my best. I have created a PR at [https://github.com/apache/commons-pool/pull/385] * The PR adds a test to demonstrate that the value of getMaxActive can be a negative number. * The PR also proposes a solution to fix this issue. During my debugging, I found that when the returned objects were being added back to the queue of the idle objects, there was a possibility where they could have been invalidated by another thread leading to invalid objects being added back to the queue of the idle objects which is not desirable. I am eager to know you critical thoughts on this. Thanks! was (Author: JIRAUSER308107): Hi [~ggregory]. Hope you are well. I really thought about your comment last year to focus on bug fixes. I have tried my best. I have created a PR at [https://github.com/apache/commons-pool/pull/385|https://github.com/apache/commons-pool/pull/385] * The PR adds a test to demonstrate that the value of getMaxActive can be a negative number. * The PR also proposes a solution to fix this issue. During my debugging, I found that when the returned objects were being added back to the set of the idle objects, there was a possibility where they could have been invalidated by another thread leading to invalid objects being added back to the pool which is not desirable. I am eager to know you critical thoughts on this. Thanks! > GenericObjectPoolConfig getNumActive return negative value > ---------------------------------------------------------- > > Key: POOL-419 > URL: https://issues.apache.org/jira/browse/POOL-419 > Project: Commons Pool > Issue Type: Bug > Affects Versions: 2.12.0 > Reporter: john ms > Priority: Major > > We've notice unexpected counting that is return from getNumActive . > and it means that allObjects and idleObjects are out of sync. > Calling returnObject and invalidateObject on the same pooled object from two > different threads is causing getNumActive to return negative value. > Why two threads are working on the same object at the same time and the real > running use case is much complex to described and not relevant, I think. > Bellow is a simple program to demo the behavior > {*}Expected result{*}: > getNumActive=0 > > {*}Actual result{*}: > getNumActive=\{negative number} > If it help debugging the RC, I've notice that returnObject is not > synchronized over pooled object and verify it's status before using it, like > it's done in invalidateObject. > {*}Workaround{*}: > Synchronize the pooled object before calling returnObject/invalidateObject > > Java 17 > {code:java} > public class PoolObject extends BasePooledObjectFactory<PoolObject> { > @Override > public PoolObject create() { > return new PoolObject(); > } > @Override > public PooledObject<PoolObject> wrap(PoolObject poolObject) { > return new DefaultPooledObject<>(poolObject); > } > @Override > public void passivateObject(PooledObject<PoolObject> pooledObject) { > } > }{code} > > {code:java} > public static void main (String [] args) throws Exception { > ExecutorService executor = Executors.newCachedThreadPool(); > GenericObjectPoolConfig<PoolObject> poolConfig = new > GenericObjectPoolConfig<>(); > poolConfig.setMaxTotal(200000); > poolConfig.setMaxIdle(200000); > poolConfig.setMinIdle(200000); > ObjectPool<PoolObject> objectPool = new GenericObjectPool<>(new > PoolObject(), poolConfig); > for (int i=0; i<1000000; i++){ > PoolObject poolObject= objectPool.borrowObject(); > FutureTask invalidateObject = new FutureTask<>(() -> { > Thread.sleep(RandomUtils.nextInt(0,10)); > //synchronized (poolObject) { // Workaround bug > objectPool.invalidateObject(poolObject); > //} > return true; > }); > executor.execute(invalidateObject); > FutureTask returnObject = new FutureTask<>(() -> { > Thread.sleep(RandomUtils.nextInt(0,10)); > //synchronized (poolObject) { // Workaround bug > objectPool.returnObject(poolObject); > //} > return true; > }); > executor.execute(returnObject); > } > Thread.sleep(2000); > executor.shutdown(); > System.out.println("getNumActive=" + objectPool.getNumActive()); > }{code} > > -- This message was sent by Atlassian Jira (v8.20.10#820010)