From b0988bc50aba24a6a3ba20ce7f7a105cef10910c Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 18 Feb 2023 16:20:06 -0500 Subject: [PATCH] Add a hard cap of 200 threads to VelocityScheduler This is a more realistic (generalized) solution for #943. Fundamentally, a plugin should not be spawning an unbounded number of asynchronous task execution units on demand from the user - an invariant Velocity itself enforces. However, since this practice is so commonplace, it makes sense that we would need to have some upper cap to at least make the practice safer than it currently is. --- .../proxy/scheduler/VelocityScheduler.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/scheduler/VelocityScheduler.java b/proxy/src/main/java/com/velocitypowered/proxy/scheduler/VelocityScheduler.java index 4e79d3c21..ca69069ea 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/scheduler/VelocityScheduler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/scheduler/VelocityScheduler.java @@ -34,8 +34,10 @@ import java.util.IdentityHashMap; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import org.apache.logging.log4j.LogManager; @@ -51,6 +53,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ public class VelocityScheduler implements Scheduler { + private static final int MAX_SCHEDULER_POOLED_THREAD_CAP = 200; + private final PluginManager pluginManager; private final ExecutorService taskService; private final ScheduledExecutorService timerExecutionService; @@ -64,8 +68,10 @@ public class VelocityScheduler implements Scheduler { */ public VelocityScheduler(PluginManager pluginManager) { this.pluginManager = pluginManager; - this.taskService = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setDaemon(true) - .setNameFormat("Velocity Task Scheduler - #%d").build()); + this.taskService = new ThreadPoolExecutor(1, MAX_SCHEDULER_POOLED_THREAD_CAP, + 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), + new ThreadFactoryBuilder().setDaemon(true) + .setNameFormat("Velocity Task Scheduler - #%d").build()); this.timerExecutionService = Executors .newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setDaemon(true) .setNameFormat("Velocity Task Scheduler Timer").build());