[jira] [Commented] (POOL-404) No way to close evictor thread
[ https://issues.apache.org/jira/browse/POOL-404?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17481433#comment-17481433 ] Patrick Barry commented on POOL-404: The connections we borrow have a wrapper around them provided by lettuce. The wrapper implements Closeable and so when you put in a try-with-resources block, close is called and the wrapper code returns connection to pool. > No way to close evictor thread > -- > > Key: POOL-404 > URL: https://issues.apache.org/jira/browse/POOL-404 > Project: Commons Pool > Issue Type: Bug >Affects Versions: 2.11.1 >Reporter: Patrick Barry >Priority: Major > > Using GenericObjectPool> to help with > lettuce client/redis connection management. I have everything shutting down > cleanly except the commons-pool-evictor. I see this problem has been > reported many times in the past, but all the changes are still not allowing > this thread to shut down cleanly on close. I am using version 2.11.1. I > have tried to code around this issue, but because EvictionTimer.java is so > locked down, there is very little that can done to change the behavior of how > this class interacts with GenericObjectPool. > For this thread to shutdown, the taskMap has to be empty, which it never is > in my case. So even though we call close() on the pool, this class fails to > shutdown the embedded executor because it thinks it has more tasks. > Looking at this code, it did remove 1 entry from taskMap, but we had many > more in that map. Is there a way to clear this map, so it will allow this > thread/executor to shutdown? > {code:java} > static synchronized void cancel(final BaseGenericObjectPool.Evictor > evictor, final Duration timeout, > final boolean restarting) { > if (evictor != null) { > evictor.cancel(); //why does this not interrupt!? > remove(evictor); > } > if (!restarting && executor != null && taskMap.isEmpty()) { //<-- How do > you force taskMap to be empty!? > executor.shutdown(); > try { > executor.awaitTermination(timeout.toMillis(), > TimeUnit.MILLISECONDS); > } catch (final InterruptedException e) { > // Swallow > // Significant API changes would be required to propagate this > } > executor.setCorePoolSize(0); > executor = null; > } > }{code} > } > I had all these entries in the taskMap when trying to shut down: > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@73d4066e > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@3c69362a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2412a42b > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@45404d5 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@29138d3a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5cbe2654 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6dbcf214 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@496a31da > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@7c251f90 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@51841ac6 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5ba26eb0 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@435e60ff > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@17d32e9b > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@66f0548d > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2e6f610d > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@1e86a5a7 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@10afe71a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@741f8dbe > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@212dfd39 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@a2ddf26 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@49ede9c7 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@65d57e4e > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6daf7d37 > *Method calls:* > pool.close() -> > stopEvictor(); -> > startEvictor(Duration.ofMillis(-1L)); -> > EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false); -> > -- This message was sent by Atlassian Jira (v8.20.1#820001)
[jira] [Commented] (POOL-404) No way to close evictor thread
[ https://issues.apache.org/jira/browse/POOL-404?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17481366#comment-17481366 ] Patrick Barry commented on POOL-404: After adding thread safety code to our class(synchronized methods), I cannot reproduce my issue. So I guess it is resolved on my end. I am still scratching my head how I had so many entries in the taskMap and it would have been nice to have a forceClose on the objectPool that would have closed down everything. In regards to the weird naming issue on the pool's threads, I opened a ticket with lettuce team. https://github.com/lettuce-io/lettuce-core/issues/1972 > No way to close evictor thread > -- > > Key: POOL-404 > URL: https://issues.apache.org/jira/browse/POOL-404 > Project: Commons Pool > Issue Type: Bug >Affects Versions: 2.11.1 >Reporter: Patrick Barry >Priority: Major > > Using GenericObjectPool> to help with > lettuce client/redis connection management. I have everything shutting down > cleanly except the commons-pool-evictor. I see this problem has been > reported many times in the past, but all the changes are still not allowing > this thread to shut down cleanly on close. I am using version 2.11.1. I > have tried to code around this issue, but because EvictionTimer.java is so > locked down, there is very little that can done to change the behavior of how > this class interacts with GenericObjectPool. > For this thread to shutdown, the taskMap has to be empty, which it never is > in my case. So even though we call close() on the pool, this class fails to > shutdown the embedded executor because it thinks it has more tasks. > Looking at this code, it did remove 1 entry from taskMap, but we had many > more in that map. Is there a way to clear this map, so it will allow this > thread/executor to shutdown? > {code:java} > static synchronized void cancel(final BaseGenericObjectPool.Evictor > evictor, final Duration timeout, > final boolean restarting) { > if (evictor != null) { > evictor.cancel(); //why does this not interrupt!? > remove(evictor); > } > if (!restarting && executor != null && taskMap.isEmpty()) { //<-- How do > you force taskMap to be empty!? > executor.shutdown(); > try { > executor.awaitTermination(timeout.toMillis(), > TimeUnit.MILLISECONDS); > } catch (final InterruptedException e) { > // Swallow > // Significant API changes would be required to propagate this > } > executor.setCorePoolSize(0); > executor = null; > } > }{code} > } > I had all these entries in the taskMap when trying to shut down: > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@73d4066e > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@3c69362a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2412a42b > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@45404d5 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@29138d3a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5cbe2654 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6dbcf214 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@496a31da > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@7c251f90 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@51841ac6 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5ba26eb0 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@435e60ff > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@17d32e9b > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@66f0548d > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2e6f610d > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@1e86a5a7 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@10afe71a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@741f8dbe > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@212dfd39 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@a2ddf26 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@49ede9c7 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@65d57e4e > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6daf7d37 > *Method calls:* > pool.close() -> > stopEvictor(); -> > startEvictor(Duration.ofMillis(-1L)); -> > EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false); -> > -- This message was sent by Atlassian Jira (v8.20.1#820001)
[jira] [Commented] (POOL-404) No way to close evictor thread
[ https://issues.apache.org/jira/browse/POOL-404?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17480759#comment-17480759 ] Patrick Barry commented on POOL-404: Here is the test I extracted. This definitely demonstrates the confusing logging statement with incrementing pool #'s, but surprisingly does not show the evictor thread still running. Trying to figure out what is different with our mainline code. Lettuce 6.1.6Release, and latest generic pool 2.11.1 Startup a local running redis server. {code:java} package com.moproblems.core.cache.redis.client; import io.lettuce.core.ClientOptions; import io.lettuce.core.RedisClient; import io.lettuce.core.RedisURI; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.resource.DefaultClientResources; import io.lettuce.core.resource.Delay; import io.lettuce.core.resource.DirContextDnsResolver; import io.lettuce.core.support.ConnectionPoolSupport; import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; import io.netty.util.concurrent.DefaultThreadFactory; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import static java.time.Duration.*; import static java.util.concurrent.TimeUnit.MILLISECONDS; public class PoolProblem { static Logger logger = LoggerFactory.getLogger(PoolProblem.class); public static void main(String[] args) throws InterruptedException { RedisURI elasticacheUri = RedisURI.Builder.redis("localhost", 6379) .build(); Timer timer = new HashedWheelTimer(new DefaultThreadFactory("my-lettuce-timer", true)); RedisClient redisClient = RedisClient.create(DefaultClientResources.builder() .ioThreadPoolSize(8) .computationThreadPoolSize(8) .dnsResolver(new DirContextDnsResolver()) .reconnectDelay(Delay.exponential(0, 1500, MILLISECONDS, 2)) .timer(timer) .build(), elasticacheUri); redisClient.setOptions(ClientOptions.builder() .autoReconnect(true) .cancelCommandsOnReconnectFailure(true) .disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS) .pingBeforeActivateConnection(true) .requestQueueSize(10) .build()); GenericObjectPoolConfig> config = new GenericObjectPoolConfig<>(); config.setMinIdle(2); config.setMaxTotal(10); config.setMaxIdle(10); config.setMaxWait(ofSeconds(1)); config.setMinEvictableIdleTime(ofMinutes(5)); config.setTestOnBorrow(true); config.setTimeBetweenEvictionRuns(ofMinutes(5)); List> tasks = new ArrayList<>(); GenericObjectPool> pool = ConnectionPoolSupport.createGenericObjectPool(redisClient::connect, config); for (int i = 0; i < 5; i++) { ExecutorService execService = Executors.newFixedThreadPool(25); for (int count = 0; count < 100; count++) { Callable c = () -> { try (StatefulRedisConnection connection = pool.borrowObject()) { logger.info("Running test on pool {}, connection {}", System.identityHashCode(pool), System.identityHashCode(connection)); Thread.sleep(100); return connection.sync().set("key", "100"); } catch (Exception e) { e.printStackTrace(); } return "{}"; }; tasks.add(c); } List> results = execService.invokeAll(tasks); logger.info("Completed {} tests", results.size()); execService.shutdownNow(); } logger.info("Done"); timer.stop(); pool.close(); redisClient.shutdown(ZERO, Duration.ofSeconds(20)); List threadsStillAlive = new ArrayList<>(); for (Thread t : Thread.getAllStackTraces().keySet()) { if (t.getName().contains("lettuce-") || t.getName().contains("pool")) { threadsStillAlive.add(t.getName()); } } logger.info("Threads still alive after attempted shutdown: {}", threadsStillAlive); } } {code} > No way to close evictor thread > -- > > Key: POOL-404 > URL: https://issues.apache.org/jira/browse/POOL-404 > Project: Commons Pool > Issue Type: Bug >Affects Versions: 2.11.1 >Reporter: Patrick
[jira] [Commented] (POOL-404) No way to close evictor thread
[ https://issues.apache.org/jira/browse/POOL-404?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17480742#comment-17480742 ] Patrick Barry commented on POOL-404: I just did some more testing. When I iterate through the threads, I print out the pool's System.identityHashCode. I was expecting to see to differences, however, I only ever see one hashcode print out, even though the logging output shows different pool numbers. logger.info("Running test on pool {}", System.identityHashCode(pool)); {code:java} 17:14:57.214 [pool-1-thread-3] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.214 [pool-1-thread-5] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.214 [pool-1-thread-4] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.214 [pool-1-thread-2] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.214 [pool-1-thread-1] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.319 [main] INFO c.g.i.c.c.redis.client.PoolProblem - Completed 5 tests 17:14:57.319 [pool-2-thread-1] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.319 [pool-2-thread-2] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.319 [pool-2-thread-3] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.320 [pool-2-thread-4] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.320 [pool-2-thread-5] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.369 [pool-2-thread-5] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.369 [pool-2-thread-2] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676 17:14:57.369 [pool-2-thread-3] INFO c.g.i.c.c.redis.client.PoolProblem - Running test on pool 1025001676{code} The test here uses one pool reference and hits it with multiple threads. > No way to close evictor thread > -- > > Key: POOL-404 > URL: https://issues.apache.org/jira/browse/POOL-404 > Project: Commons Pool > Issue Type: Bug >Affects Versions: 2.11.1 >Reporter: Patrick Barry >Priority: Major > > Using GenericObjectPool> to help with > lettuce client/redis connection management. I have everything shutting down > cleanly except the commons-pool-evictor. I see this problem has been > reported many times in the past, but all the changes are still not allowing > this thread to shut down cleanly on close. I am using version 2.11.1. I > have tried to code around this issue, but because EvictionTimer.java is so > locked down, there is very little that can done to change the behavior of how > this class interacts with GenericObjectPool. > For this thread to shutdown, the taskMap has to be empty, which it never is > in my case. So even though we call close() on the pool, this class fails to > shutdown the embedded executor because it thinks it has more tasks. > Looking at this code, it did remove 1 entry from taskMap, but we had many > more in that map. Is there a way to clear this map, so it will allow this > thread/executor to shutdown? > {code:java} > static synchronized void cancel(final BaseGenericObjectPool.Evictor > evictor, final Duration timeout, > final boolean restarting) { > if (evictor != null) { > evictor.cancel(); //why does this not interrupt!? > remove(evictor); > } > if (!restarting && executor != null && taskMap.isEmpty()) { //<-- How do > you force taskMap to be empty!? > executor.shutdown(); > try { > executor.awaitTermination(timeout.toMillis(), > TimeUnit.MILLISECONDS); > } catch (final InterruptedException e) { > // Swallow > // Significant API changes would be required to propagate this > } > executor.setCorePoolSize(0); > executor = null; > } > }{code} > } > I had all these entries in the taskMap when trying to shut down: > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@73d4066e > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@3c69362a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2412a42b > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@45404d5 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@29138d3a > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5cbe2654 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6dbcf214 > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@496a31da > org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@7c251f90 >
[jira] [Commented] (POOL-404) No way to close evictor thread
[ https://issues.apache.org/jira/browse/POOL-404?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17480739#comment-17480739 ] Patrick Barry commented on POOL-404: [~psteitz] My intention is to only have 1 pool for lettuce connections to redis servers. However, I did find it strange in my testing that the thread name was incrementing the pool # as well as thread #. However, in using jconsole, I confirmed I only ever see 1 pool in the mbeans, as well as the constructor of GenericObjectPool is only ever called once. So I cannot explain why I have so many items in the taskMap. In my test, I create the pool and then I call pool.borrowObject() using multiple threads. https://github.com/lettuce-io/lettuce-core/blob/main/src/main/java/io/lettuce/core/support/ConnectionPoolSupport.java 09:46:10.892 [pool-1-thread-1] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:10.892 [pool-1-thread-15] INFO c.g.i.c.c.r.ManualSingleConnectionTest 09:46:10.893 [pool-1-thread-16] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:10.893 [pool-1-thread-6] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:10.893 [pool-1-thread-22] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:10.893 [pool-1-thread-17] INFO c.g.i.c.c.r.ManualSingleConnectionTest 09:46:10.893 [pool-1-thread-7] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:10.893 [pool-1-thread-2] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 25 commands took 1814ms. 0 succeeded. 0 failed 09:46:11.440 [pool-2-thread-2] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:11.441 [pool-2-thread-1] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:11.441 [pool-2-thread-4] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:11.441 [pool-2-thread-5] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:11.441 [pool-2-thread-3] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:11.441 [pool-2-thread-6] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:11.441 [pool-2-thread-7] INFO c.g.i.c.c.r.ManualSingleConnectionTest - 09:46:11.441 [pool-2-thread-8] INFO c.g.i.c.c.r.ManualSingleConnectionTest - In the lettuce library, we create a new GenericObjectPool using this code: (io.lettuce.core.support.ConnectionPoolSupport) ConnectionPoolSupport.createGenericObjectPool(redisClient::connect, objPoolConfig); which creates a pool using this code: {code:java} GenericObjectPool pool = new GenericObjectPool(new ConnectionPoolSupport.RedisPooledObjectFactory(connectionSupplier), config) { public T borrowObject() throws Exception { return wrapConnections ? (StatefulConnection)ConnectionWrapping.wrapConnection(super.borrowObject(), (Origin)poolRef.get()) : (StatefulConnection)super.borrowObject(); } public void returnObject(T obj) { if (wrapConnections && obj instanceof HasTargetConnection) { super.returnObject(((HasTargetConnection)obj).getTargetConnection()); } else { super.returnObject(obj); } } }; poolRef.set(new ConnectionPoolSupport.ObjectPoolWrapper(pool)); return pool{code} > No way to close evictor thread > -- > > Key: POOL-404 > URL: https://issues.apache.org/jira/browse/POOL-404 > Project: Commons Pool > Issue Type: Bug >Affects Versions: 2.11.1 >Reporter: Patrick Barry >Priority: Major > > Using GenericObjectPool> to help with > lettuce client/redis connection management. I have everything shutting down > cleanly except the commons-pool-evictor. I see this problem has been > reported many times in the past, but all the changes are still not allowing > this thread to shut down cleanly on close. I am using version 2.11.1. I > have tried to code around this issue, but because EvictionTimer.java is so > locked down, there is very little that can done to change the behavior of how > this class interacts with GenericObjectPool. > For this thread to shutdown, the taskMap has to be empty, which it never is > in my case. So even though we call close() on the pool, this class fails to > shutdown the embedded executor because it thinks it has more tasks. > Looking at this code, it did remove 1 entry from taskMap, but we had many > more in that map. Is there a way to clear this map, so it will allow this > thread/executor to shutdown? > {code:java} > static synchronized void cancel(final BaseGenericObjectPool.Evictor > evictor, final Duration timeout, > final boolean restarting) { > if (evictor != null) { > evictor.cancel(); //why does this not interrupt!? > remove(evictor); > } > if (!restarting && executor != null && taskMap.isEmpty()) { //<-- How do > you force taskMap to be empty!? > executor.shutdown(); > try { > executor.awaitTermination(timeout.toMillis(), > TimeUnit.MILLISECONDS); > } catch (final InterruptedException e) { > //
[jira] [Updated] (POOL-404) No way to close evictor thread
[ https://issues.apache.org/jira/browse/POOL-404?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Patrick Barry updated POOL-404: --- Description: Using GenericObjectPool> to help with lettuce client/redis connection management. I have everything shutting down cleanly except the commons-pool-evictor. I see this problem has been reported many times in the past, but all the changes are still not allowing this thread to shut down cleanly on close. I am using version 2.11.1. I have tried to code around this issue, but because EvictionTimer.java is so locked down, there is very little that can done to change the behavior of how this class interacts with GenericObjectPool. For this thread to shutdown, the taskMap has to be empty, which it never is in my case. So even though we call close() on the pool, this class fails to shutdown the embedded executor because it thinks it has more tasks. Looking at this code, it did remove 1 entry from taskMap, but we had many more in that map. Is there a way to clear this map, so it will allow this thread/executor to shutdown? {code:java} static synchronized void cancel(final BaseGenericObjectPool.Evictor evictor, final Duration timeout, final boolean restarting) { if (evictor != null) { evictor.cancel(); //why does this not interrupt!? remove(evictor); } if (!restarting && executor != null && taskMap.isEmpty()) { //<-- How do you force taskMap to be empty!? executor.shutdown(); try { executor.awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS); } catch (final InterruptedException e) { // Swallow // Significant API changes would be required to propagate this } executor.setCorePoolSize(0); executor = null; } }{code} } I had all these entries in the taskMap when trying to shut down: org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@73d4066e org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@3c69362a org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2412a42b org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@45404d5 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@29138d3a org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5cbe2654 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6dbcf214 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@496a31da org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@7c251f90 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@51841ac6 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5ba26eb0 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@435e60ff org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@17d32e9b org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@66f0548d org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2e6f610d org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@1e86a5a7 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@10afe71a org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@741f8dbe org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@212dfd39 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@a2ddf26 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@49ede9c7 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@65d57e4e org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6daf7d37 *Method calls:* pool.close() -> stopEvictor(); -> startEvictor(Duration.ofMillis(-1L)); -> EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false); -> was: Using GenericObjectPool> to help with lettuce client/redis connection management. I have everything shutting down cleanly except the commons-pool-evictor. I see this problem has many reported in the past, but it still not shutting down. I am using version 2.11.1. I have tried to code around this issue, but because EvictionTimer.java is so locked down, there is very little that can done to change the behavior of how this class interacts with GenericObjectPool. For this thread to shutdown, the taskMap has to be empty, which it never is in my case. So even thought we call close() on the pool, this class fails to shutdown the embedded executor because it thinks it has more tasks. Looking at this code, it did remove 1 entry from taskMap, but we had many more in that map. Is there a way to clear this map, so it will allow this thread/executor to shutdown? {code:java} static synchronized void cancel(final BaseGenericObjectPool.Evictor evictor, final Duration timeout, final boolean restarting) { if (evictor != null) { evictor.cancel(); //why does this not interrupt!? remove(evictor); } if (!restarting && executor != null && taskMap.isEmpty()) { //<-- How do you force taskMap to be empty!?
[jira] [Created] (POOL-404) No way to close evictor thread
Patrick Barry created POOL-404: -- Summary: No way to close evictor thread Key: POOL-404 URL: https://issues.apache.org/jira/browse/POOL-404 Project: Commons Pool Issue Type: Bug Affects Versions: 2.11.1 Reporter: Patrick Barry Using GenericObjectPool> to help with lettuce client/redis connection management. I have everything shutting down cleanly except the commons-pool-evictor. I see this problem has many reported in the past, but it still not shutting down. I am using version 2.11.1. I have tried to code around this issue, but because EvictionTimer.java is so locked down, there is very little that can done to change the behavior of how this class interacts with GenericObjectPool. For this thread to shutdown, the taskMap has to be empty, which it never is in my case. So even thought we call close() on the pool, this class fails to shutdown the embedded executor because it thinks it has more tasks. Looking at this code, it did remove 1 entry from taskMap, but we had many more in that map. Is there a way to clear this map, so it will allow this thread/executor to shutdown? {code:java} static synchronized void cancel(final BaseGenericObjectPool.Evictor evictor, final Duration timeout, final boolean restarting) { if (evictor != null) { evictor.cancel(); //why does this not interrupt!? remove(evictor); } if (!restarting && executor != null && taskMap.isEmpty()) { //<-- How do you force taskMap to be empty!? executor.shutdown(); try { executor.awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS); } catch (final InterruptedException e) { // Swallow // Significant API changes would be required to propagate this } executor.setCorePoolSize(0); executor = null; } }{code} } I had all these entries in the taskMap when trying to shut down: org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@73d4066e org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@3c69362a org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2412a42b org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@45404d5 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@29138d3a org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5cbe2654 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6dbcf214 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@496a31da org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@7c251f90 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@51841ac6 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@5ba26eb0 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@435e60ff org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@17d32e9b org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@66f0548d org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@2e6f610d org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@1e86a5a7 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@10afe71a org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@741f8dbe org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@212dfd39 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@a2ddf26 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@49ede9c7 org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@65d57e4e org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor@6daf7d37 *Method calls:* pool.close() -> stopEvictor(); -> startEvictor(Duration.ofMillis(-1L)); -> EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false); -> -- This message was sent by Atlassian Jira (v8.20.1#820001)