Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
From 076e7a2e1a2f118de921b5843e3baa4a75cadbbc Mon Sep 17 00:00:00 2001
From: A248 <theanandbeh@gmail.com>
Date: Mon, 21 Aug 2023 13:38:03 -0500
Subject: [PATCH] Proof methods in Plugin, PluginManager against concurrent
access


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 3d1e9a3a..b4d2dd51 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
@@ -113,17 +113,29 @@ public class Plugin
}

//
- private ExecutorService service;
+ private volatile ExecutorService service; // Waterfall - mark volatile

@Deprecated
public ExecutorService getExecutorService()
{
+ // Waterfall start - synchronize
+ ExecutorService service = this.service;
if ( service == null )
{
- String name = ( getDescription() == null ) ? "unknown" : getDescription().getName();
- service = Executors.newCachedThreadPool( new ThreadFactoryBuilder().setNameFormat( name + " Pool Thread #%1$d" )
- .setThreadFactory( new GroupedThreadFactory( this, name ) ).build() );
+ synchronized ( this )
+ {
+ service = this.service;
+ if ( service == null )
+ {
+ String name = ( getDescription() == null ) ? "unknown" : getDescription().getName();
+ service = Executors
+ .newCachedThreadPool( new ThreadFactoryBuilder().setNameFormat( name + " Pool Thread #%1$d" )
+ .setThreadFactory( new GroupedThreadFactory( this, name ) ).build() );
+ this.service = service;
+ }
+ }
}
+ // Waterfall end
return service;
}
//
diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
index 1ba5b249..f858e281 100644
--- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
+++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
@@ -60,7 +60,7 @@ public final class PluginManager
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
private final MutableGraph<String> dependencyGraph = GraphBuilder.directed().build();
private final LibraryLoader libraryLoader;
- private final Map<String, Command> commandMap = new HashMap<>();
+ private final Map<String, Command> commandMap = new java.util.concurrent.ConcurrentHashMap<>(); // Waterfall - thread safe
private Map<String, PluginDescription> toLoad = new HashMap<>();
private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
private final Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create();
@@ -99,12 +99,14 @@ public final class PluginManager
*/
public void registerCommand(Plugin plugin, Command command)
{
+ synchronized ( commandsByPlugin ) { // Waterfall - synchronize mutation
commandMap.put( command.getName().toLowerCase( Locale.ROOT ), command );
for ( String alias : command.getAliases() )
{
commandMap.put( alias.toLowerCase( Locale.ROOT ), command );
}
commandsByPlugin.put( plugin, command );
+ } // Waterfall
}

/**
@@ -114,8 +116,12 @@ public final class PluginManager
*/
public void unregisterCommand(Command command)
{
- while ( commandMap.values().remove( command ) );
- commandsByPlugin.values().remove( command );
+ // Waterfall start - synchronize mutation
+ synchronized ( commandsByPlugin ) {
+ while ( commandMap.values().remove( command ) );
+ commandsByPlugin.values().remove( command );
+ }
+ // Waterfall end
}

/**
@@ -125,12 +131,14 @@ public final class PluginManager
*/
public void unregisterCommands(Plugin plugin)
{
+ synchronized ( commandsByPlugin ) { // Waterfall - synchronize mutation
for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); )
{
Command command = it.next();
while ( commandMap.values().remove( command ) );
it.remove();
}
+ } // Waterfall
}

private Command getCommandIfEnabled(String commandName, CommandSender sender)
@@ -278,7 +286,7 @@ public final class PluginManager
*/
public Collection<Plugin> getPlugins()
{
- return plugins.values();
+ synchronized ( plugins ) { return new java.util.ArrayList<>( plugins.values() ); } // Waterfall - synchronize
}

/**
@@ -289,7 +297,7 @@ public final class PluginManager
*/
public Plugin getPlugin(String name)
{
- return plugins.get( name );
+ synchronized ( plugins ) { return plugins.get( name ); } // Waterfall - synchronize
}

public void loadPlugins()
@@ -395,7 +403,7 @@ public final class PluginManager
Class<?> main = loader.loadClass( plugin.getMain() );
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();

- plugins.put( plugin.getName(), clazz );
+ synchronized ( plugins ) { plugins.put( plugin.getName(), clazz ); } // Waterfall - synchronize
clazz.onLoad();
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]
{
@@ -501,8 +509,13 @@ public final class PluginManager
Preconditions.checkArgument( !method.isAnnotationPresent( Subscribe.class ),
"Listener %s has registered using deprecated subscribe annotation! Please update to @EventHandler.", listener );
}
- eventBus.register( listener );
- listenersByPlugin.put( plugin, listener );
+ // Waterfall start - synchronize mutation
+ synchronized ( listenersByPlugin )
+ {
+ eventBus.register( listener );
+ listenersByPlugin.put( plugin, listener );
+ }
+ // Waterfall end
}

/**
@@ -512,8 +525,13 @@ public final class PluginManager
*/
public void unregisterListener(Listener listener)
{
- eventBus.unregister( listener );
- listenersByPlugin.values().remove( listener );
+ // Waterfall start - synchronize mutation
+ synchronized ( listenersByPlugin )
+ {
+ eventBus.unregister( listener );
+ listenersByPlugin.values().remove( listener );
+ }
+ // Waterfall end
}

/**
@@ -523,11 +541,13 @@ public final class PluginManager
*/
public void unregisterListeners(Plugin plugin)
{
+ synchronized ( listenersByPlugin ) { // Waterfall - synchronize mutation
for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); )
{
eventBus.unregister( it.next() );
it.remove();
}
+ } // Waterfall
}

/**
--
2.30.2