diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java b/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java index caa7f5e7..98b3f57d 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java @@ -1,11 +1,16 @@ package net.md_5.bungee.api.plugin; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.io.File; import java.io.InputStream; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import java.util.logging.Logger; import lombok.Getter; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ConfigurationAdapter; +import net.md_5.bungee.api.scheduler.GroupedThreadFactory; /** * Represents any Plugin that may be loaded at runtime to enhance existing @@ -83,4 +88,19 @@ public class Plugin this.file = description.getFile(); this.logger = new PluginLogger( this ); } + + // + private ExecutorService service; + + @Deprecated + public ExecutorService getExecutorService() + { + if ( service == null ) + { + service = Executors.newCachedThreadPool( new ThreadFactoryBuilder().setNameFormat( getDescription().getName() + " Pool Thread #%1$d" ) + .setThreadFactory( new GroupedThreadFactory( this ) ).build() ); + } + return service; + } + // } diff --git a/api/src/main/java/net/md_5/bungee/api/scheduler/GroupedThreadFactory.java b/api/src/main/java/net/md_5/bungee/api/scheduler/GroupedThreadFactory.java new file mode 100644 index 00000000..8bd65a99 --- /dev/null +++ b/api/src/main/java/net/md_5/bungee/api/scheduler/GroupedThreadFactory.java @@ -0,0 +1,34 @@ +package net.md_5.bungee.api.scheduler; + +import java.util.concurrent.ThreadFactory; +import lombok.Data; +import net.md_5.bungee.api.plugin.Plugin; + +@Data +@Deprecated +public class GroupedThreadFactory implements ThreadFactory +{ + + private final ThreadGroup group; + + public class BungeeGroup extends ThreadGroup + { + + private BungeeGroup(String name) + { + super( name ); + } + + } + + public GroupedThreadFactory(Plugin plugin) + { + this.group = new BungeeGroup( plugin.getDescription().getName() ); + } + + @Override + public Thread newThread(Runnable r) + { + return new Thread( group, r ); + } +} diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index 638d9111..0a3900f8 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -366,9 +366,9 @@ public class BungeeCord extends ProxyServer t.printStackTrace(); } getScheduler().cancel( plugin ); + plugin.getExecutorService().shutdownNow(); } - scheduler.shutdown(); getLogger().info( "Thank you and goodbye" ); // Need to close loggers after last message! for ( Handler handler : getLogger().getHandlers() ) diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeSecurityManager.java b/proxy/src/main/java/net/md_5/bungee/BungeeSecurityManager.java index 6c56d4e6..b8b1664e 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeSecurityManager.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeSecurityManager.java @@ -4,6 +4,7 @@ import java.security.AccessControlException; import java.security.Permission; import java.util.logging.Level; import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.scheduler.GroupedThreadFactory; public class BungeeSecurityManager extends SecurityManager { @@ -54,10 +55,12 @@ public class BungeeSecurityManager extends SecurityManager } @Override - public ThreadGroup getThreadGroup() + public void checkAccess(ThreadGroup g) { - checkRestricted( "Thread Creation: Use scheduler" ); - return super.getThreadGroup(); + if ( !( g instanceof GroupedThreadFactory.BungeeGroup ) ) + { + checkRestricted( "Illegal thread group access" ); + } } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java index 2d0cc2da..2f899965 100644 --- a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java +++ b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java @@ -4,14 +4,12 @@ import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import gnu.trove.TCollections; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import net.md_5.bungee.api.plugin.Plugin; @@ -21,7 +19,6 @@ import net.md_5.bungee.api.scheduler.TaskScheduler; public class BungeeScheduler implements TaskScheduler { - private final ExecutorService s = Executors.newCachedThreadPool( new ThreadFactoryBuilder().setNameFormat( "Bungee Pool Thread #%1$d" ).build() ); private final AtomicInteger taskCounter = new AtomicInteger(); private final TIntObjectMap tasks = TCollections.synchronizedMap( new TIntObjectHashMap() ); private final Multimap tasksByPlugin = Multimaps.synchronizedMultimap( HashMultimap.create() ); @@ -32,15 +29,10 @@ public class BungeeScheduler implements TaskScheduler @Override public ExecutorService getExecutorService(Plugin plugin) { - return s; + return plugin.getExecutorService(); } }; - public void shutdown() - { - s.shutdown(); - } - @Override public void cancel(int id) { @@ -89,7 +81,7 @@ public class BungeeScheduler implements TaskScheduler Preconditions.checkNotNull( task, "task" ); BungeeTask prepared = new BungeeTask( this, taskCounter.getAndIncrement(), owner, task, delay, period, unit ); tasks.put( prepared.getId(), prepared ); - s.execute( prepared ); + owner.getExecutorService().execute( prepared ); return prepared; }