[
https://issues.apache.org/jira/browse/POOL-407?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17614290#comment-17614290
]
Gary D. Gregory edited comment on POOL-407 at 10/7/22 10:02 PM:
----------------------------------------------------------------
Hello [~dmfs]
For your use case, I added the test package
{{org.apache.commons.pool2.pool407}} which contains a configurable set of test
classes based on your git repo.
The simplest way to fix your issue is to not create a bogus pooled object by
updating your factory from:
{code:java}
@Override
public PooledObject<KeyedPool407Fixture> wrap(final KeyedPool407Fixture
value) {
return new DefaultPooledObject<>(value,);
}
{code:}
to:
{code:java}
@Override
public PooledObject<KeyedPool407Fixture> wrap(final KeyedPool407Fixture
value) {
// Require a non-null value.
return new DefaultPooledObject<>(Objects.requireNonNull(value,
"value"));
}
{code}
One would think that changing the validation method only should work, but the
following is not enough:
{code:java}
@Override
public boolean validateObject(final String key, final
PooledObject<KeyedPool407Fixture> p) {
// TODO Should this be enough even if wrap() does throw and returns a
DefaultPooledObject wrapping a null?
return p.getObject() != null;
}
{code}
was (Author: garydgregory):
Hello [~dmfs]
For your use case, I added the test package
{{org.apache.commons.pool2.pool407}} which contains a configurable set of test
classes based on your git repo.
The simplest way to fix your issue is to not create a bogus pooled object by
updating your factory from:
{code:java}
@Override
public PooledObject<KeyedPool407Fixture> wrap(final KeyedPool407Fixture
value) {
return new DefaultPooledObject<>(value,);
}
{code:}
to:
{code:java}
@Override
public PooledObject<KeyedPool407Fixture> wrap(final KeyedPool407Fixture
value) {
// Require a non-null value.
return new DefaultPooledObject<>(Objects.requireNonNull(value,
"value"));
}
{code}
One would think that changing the validation method only should work, but the
following is not enough:
{code:java}
@Override
public boolean validateObject(final String key, final
PooledObject<KeyedPool407Fixture> p) {
// TODO Should this be enough even if wrap() does throw and returns a
DefaultPooledObject wrapping a null?
return p.getObject() != null;
}
{code:java}
> Threads get stuck when idleObjects list is empty.
> -------------------------------------------------
>
> Key: POOL-407
> URL: https://issues.apache.org/jira/browse/POOL-407
> Project: Commons Pool
> Issue Type: Bug
> Affects Versions: 2.8.1
> Reporter: Sarthak Shukla
> Priority: Major
>
> While borrowing object from pool, threads are getting stuck. I initialised
> the pool size as 1. And had 3 threads created. First thread enters
> borrowObject method, since there are no idle objects to poll from, it will
> create one object and move forward.
> {code:java}
> p = (PooledObject)this.idleObjects.pollFirst();
> if (p == null) {
> p = this.create();
> if (p != null) {
> create = true;
> }
> } {code}
> The other two threads will also follow same path and check for idle
> objects(there are none), will try to create one object but the pool size is
> set to 1. Thus, the two threads will move forward and enter
> *idleObjects.takeFirst()* function. Value of blockWhenExhausted is true and
> borrowMaxWaitMillis is -1 as we don't want timeout.
> {code:java}
> if (blockWhenExhausted) {
> if (p == null) {
> if (borrowMaxWaitMillis < 0L) {
> p = (PooledObject)this.idleObjects.takeFirst();
> } else {
> p = (PooledObject)this.idleObjects.pollFirst(borrowMaxWaitMillis,
> TimeUnit.MILLISECONDS);
> }
> }
> if (p == null) {
> throw new NoSuchElementException("Timeout waiting for idle object");
> }
> }{code}
> Now, the main thread does *this.factory.activateObject(p);* and object gets
> activated. Now, when the validation is checked *validate =
> this.factory.validateObject(p);* it comes out to be false as provider might
> have been disconnected.
> So, the object is destroyed by calling *this.destroy(p);*
> {code:java}
> private void destroy(PooledObject<T> toDestroy) throws Exception {
> toDestroy.invalidate();
> this.idleObjects.remove(toDestroy);
> this.allObjects.remove(new
> BaseGenericObjectPool.IdentityWrapper(toDestroy.getObject()));
> try {
> this.factory.destroyObject(toDestroy);
> } finally {
> this.destroyedCount.incrementAndGet();
> this.createCount.decrementAndGet();
> }
> }{code}
> The object which was created is now destroyed and removed from idleObject and
> allObjects list. Now, the other two threads are still waiting to take object
> from idle objects list but there are no object present. Hence, the two
> threads are in wait state for infinite period and the application waits
> forever until we kill the process.
> {code:java}
> public E takeFirst() throws InterruptedException {
> this.lock.lock();
> Object var2;
> try {
> Object x;
> while((x = this.unlinkFirst()) == null) {
> this.notEmpty.await();
> }
> var2 = x;
> } finally {
> this.lock.unlock();
> }
> return var2;
> } {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)