From 77e30e246d179e5b84ad6079a7f7f1d28b5fff20 Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Fri, 21 Jan 2022 09:09:32 -0500 Subject: [PATCH] Util: Fix leak of SimpleTimer2 shutdown task --- core/java/src/net/i2p/I2PAppContext.java | 7 ++++++ core/java/src/net/i2p/util/SimpleTimer2.java | 23 +++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index 99bbd53c72..7df62046c8 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -906,6 +906,13 @@ public class I2PAppContext { public void addShutdownTask(Runnable task) { _shutdownTasks.add(task); } + + /** + * @since 0.9.53 + */ + public void removeShutdownTask(Runnable task) { + _shutdownTasks.remove(task); + } /** * @return an unmodifiable Set diff --git a/core/java/src/net/i2p/util/SimpleTimer2.java b/core/java/src/net/i2p/util/SimpleTimer2.java index b6c6deaef7..f2723dbb73 100644 --- a/core/java/src/net/i2p/util/SimpleTimer2.java +++ b/core/java/src/net/i2p/util/SimpleTimer2.java @@ -41,6 +41,8 @@ public class SimpleTimer2 { private final String _name; private final AtomicInteger _count = new AtomicInteger(); private final int _threads; + private final I2PAppContext _context; + private final Runnable _shutdown; /** * To be instantiated by the context. @@ -64,14 +66,15 @@ public class SimpleTimer2 { * @since 0.9 */ protected SimpleTimer2(I2PAppContext context, String name, boolean prestartAllThreads) { + _context = context; _name = name; long maxMemory = SystemVersion.getMaxMemory(); _threads = (int) Math.max(MIN_THREADS, Math.min(MAX_THREADS, 1 + (maxMemory / (32*1024*1024)))); _executor = new CustomScheduledThreadPoolExecutor(_threads, new CustomThreadFactory()); if (prestartAllThreads) _executor.prestartAllCoreThreads(); - // don't bother saving ref to remove hook if somebody else calls stop - context.addShutdownTask(new Shutdown()); + _shutdown = new Shutdown(); + context.addShutdownTask(_shutdown); } /** @@ -79,7 +82,7 @@ public class SimpleTimer2 { */ private class Shutdown implements Runnable { public void run() { - stop(); + stop(false); } } @@ -89,6 +92,20 @@ public class SimpleTimer2 { * Cannot be restarted. */ public void stop() { + stop(true); + } + + /** + * Stops the SimpleTimer. + * Subsequent executions should not throw a RejectedExecutionException. + * Cannot be restarted. + * + * @param removeTask true to unregister the shutdown hook + * @since 0.9.53 + */ + private void stop(boolean removeTask) { + if (removeTask) + _context.removeShutdownTask(_shutdown); _executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); _executor.shutdownNow(); } -- GitLab