This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch POOL_2_X
in repository https://gitbox.apache.org/repos/asf/commons-pool.git
The following commit(s) were added to refs/heads/POOL_2_X by this push:
new 9a5664d6 The maximum wait time for GenericObjectPool.borrowObject(*)
may exceed expectations due to a spurious thread wakeup
9a5664d6 is described below
commit 9a5664d64914f692d5dd6b71839a8368730a4cd6
Author: Gary Gregory <[email protected]>
AuthorDate: Sun Nov 24 18:12:19 2024 -0500
The maximum wait time for GenericObjectPool.borrowObject(*) may exceed
expectations due to a spurious thread wakeup
---
src/changes/changes.xml | 1 +
.../apache/commons/pool2/impl/GenericObjectPool.java | 20 +++++++++++---------
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 6c7ce5d0..0c5d6bc1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -49,6 +49,7 @@ The <action> type attribute can be add,update,fix,remove.
<!-- FIX -->
<action type="fix" dev="ggregory" due-to="Gary Gregory">Use
java.time.Instant precision in
org.apache.commons.pool2.impl.ThrowableCallStack.Snapshot throwable
message.</action>
<action type="fix" dev="ggregory" due-to="Gary
Gregory">GenericObjectPool.borrowObject(Duration) doesn't obey its
borrowMaxWait Duration argument when the argument is different from
GenericObjectPool.getMaxWaitDuration().</action>
+ <action type="fix" issue="POOL-418" dev="ggregory" due-to="Gary
Gregory">The maximum wait time for GenericObjectPool.borrowObject(*) may exceed
expectations due to a spurious thread wakeup.</action>
<!-- ADD -->
<!-- UPDATE -->
<action type="update" dev="ggregory">Bump
org.apache.commons:commons-parent from 62 to 73.</action>
diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
index f4a7c9d2..ba27b250 100644
--- a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
+++ b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
@@ -87,7 +87,9 @@ public class GenericObjectPool<T> extends
BaseGenericObjectPool<T>
"org.apache.commons.pool2:type=GenericObjectPool,name=";
private static void wait(final Object obj, final Duration duration) throws
InterruptedException {
- obj.wait(duration.toMillis(), duration.getNano() % 1_000_000);
+ if (!duration.isNegative()) {
+ obj.wait(duration.toMillis(), duration.getNano() % 1_000_000);
+ }
}
private volatile String factoryType;
@@ -506,15 +508,14 @@ public class GenericObjectPool<T> extends
BaseGenericObjectPool<T>
* @throws Exception if the object factory's {@code makeObject} fails
*/
private PooledObject<T> create(final Duration maxWaitDuration) throws
Exception {
+ final Instant startInstant = Instant.now();
+ Duration remainingWaitDuration = maxWaitDuration.isNegative() ?
Duration.ZERO : maxWaitDuration;
int localMaxTotal = getMaxTotal();
// This simplifies the code later in this method
if (localMaxTotal < 0) {
localMaxTotal = Integer.MAX_VALUE;
}
-
final Instant localStartInstant = Instant.now();
- final Duration localMaxWaitDuration = maxWaitDuration.isNegative() ?
Duration.ZERO : maxWaitDuration;
-
// Flag that indicates if create should:
// - TRUE: call the factory to create an object
// - FALSE: return null
@@ -522,6 +523,8 @@ public class GenericObjectPool<T> extends
BaseGenericObjectPool<T>
// call the factory
Boolean create = null;
while (create == null) {
+ // remainingWaitDuration handles spurious wakeup from wait().
+ remainingWaitDuration =
remainingWaitDuration.minus(durationSince(startInstant));
synchronized (makeObjectCountLock) {
final long newCreateCount = createCount.incrementAndGet();
if (newCreateCount > localMaxTotal) {
@@ -538,7 +541,7 @@ public class GenericObjectPool<T> extends
BaseGenericObjectPool<T>
// bring the pool to capacity. Those calls might also
// fail so wait until they complete and then re-test if
// the pool is at capacity or not.
- wait(makeObjectCountLock, localMaxWaitDuration);
+ wait(makeObjectCountLock, remainingWaitDuration);
}
} else {
// The pool is not at capacity. Create a new object.
@@ -546,10 +549,9 @@ public class GenericObjectPool<T> extends
BaseGenericObjectPool<T>
create = Boolean.TRUE;
}
}
-
- // Do not block more if localMaxWaitDuration > 0.
- if (create == null &&
localMaxWaitDuration.compareTo(Duration.ZERO) > 0 &&
-
durationSince(localStartInstant).compareTo(localMaxWaitDuration) >= 0) {
+ // Do not block more if remainingWaitDuration > 0.
+ if (create == null &&
remainingWaitDuration.compareTo(Duration.ZERO) > 0 &&
+
durationSince(localStartInstant).compareTo(remainingWaitDuration) >= 0) {
create = Boolean.FALSE;
}
}