1212import java .util .Comparator ;
1313import java .util .List ;
1414import java .util .Map ;
15+ import java .util .TreeMap ;
1516import java .util .TreeSet ;
1617import java .util .concurrent .ConcurrentHashMap ;
1718import java .util .concurrent .locks .ReentrantLock ;
@@ -57,7 +58,7 @@ public static void execute(Plugin plugin, RunnableWithException runnable) throws
5758 pluginsToLock = cachedDependencyLists .computeIfAbsent (plugin .getName (), (name ) -> {
5859 TreeSet <String > dependencyList = new TreeSet <>(Comparator .naturalOrder ());
5960 LOGGER .info ("Plugin {} does not support Folia! Initializing synchronous execution. This may cause a performance degradation." , plugin );
60- fillPluginsToLock (plugin , dependencyList );
61+ fillPluginsToLock (plugin , dependencyList , new ArrayList <>() );
6162 LOGGER .info ("Dependency list calculated for {}: {}" , plugin , dependencyList );
6263 return new ArrayList <>(dependencyList );
6364 });
@@ -138,25 +139,33 @@ private static boolean tryLockNow(List<String> locksToReacquire) {
138139 return success ;
139140 }
140141
141- private static boolean fillPluginsToLock (Plugin plugin , TreeSet <String > pluginsToLock ) {
142- if (!pluginsToLock .add (plugin .getName ())) {
143- // Cyclic graphhhh
144- LOGGER .error ("Cyclich graph detected for plugin {}, synchronous execution initialising failure, disabling plugin." , plugin );
145- plugin .getServer ().getPluginManager ().disablePlugin (plugin );
142+ private static boolean fillPluginsToLock (Plugin plugin , TreeSet <String > pluginsToLock , List <String > parentList ) {
143+ if (plugin .getDescription ().isFoliaSupported ()) {
144+ // Multi-thread safe plugin, we don't need to lock it
145+ return false ;
146+ }
147+
148+ if (pluginsToLock .contains (plugin .getName ())) {
149+ // Already visited
146150 return true ;
147151 }
148152
149- if (plugin .getDescription ().isFoliaSupported ()) {
150- // Multi-thread safe plugin, we don't need to lock it
153+ if (parentList .contains (plugin .getName ())) {
154+ // Cyclic graph, add all the plugins in the cycle
155+ int i = parentList .size () - 1 ;
156+ do {
157+ pluginsToLock .add (parentList .get (i ));
158+ } while (!parentList .get (i --).equals (plugin .getName ()));
151159 return false ;
152160 }
161+ parentList .add (plugin .getName ());
153162
154163 boolean hasDependency = false ;
155164
156165 for (String depend : plugin .getDescription ().getDepend ()) {
157166 Plugin dependPlugin = plugin .getServer ().getPluginManager ().getPlugin (depend );
158167 if (dependPlugin != null ) {
159- hasDependency |= fillPluginsToLock (dependPlugin , pluginsToLock );
168+ hasDependency |= fillPluginsToLock (dependPlugin , pluginsToLock , parentList );
160169 } else {
161170 LOGGER .warn ("Could not find dependency " + depend + " for plugin " + plugin .getName () + " even though it is a required dependency - this code shouldn't've been able to be run!" );
162171 }
@@ -165,14 +174,19 @@ private static boolean fillPluginsToLock(Plugin plugin, TreeSet<String> pluginsT
165174 for (String softDepend : plugin .getDescription ().getSoftDepend ()) {
166175 Plugin softDependPlugin = plugin .getServer ().getPluginManager ().getPlugin (softDepend );
167176 if (softDependPlugin != null ) {
168- hasDependency |= fillPluginsToLock (softDependPlugin , pluginsToLock );
177+ hasDependency |= fillPluginsToLock (softDependPlugin , pluginsToLock , parentList );
169178 }
170179 }
171180
172- if (hasDependency ) {
181+ if (! hasDependency ) {
173182 // Only add our own plugin if we have no dependencies to lock
174183 // If we have a dependency, there's no point in locking this plugin by itself as we'll always be locking the dependency anyway
175- pluginsToLock .remove (plugin .getName ());
184+ pluginsToLock .add (plugin .getName ());
185+ }
186+
187+ String lastRemoved = parentList .removeLast ();
188+ if (!lastRemoved .equals (plugin .getName ())) {
189+ LOGGER .error ("Removed wrong last plugin from parentList. Expected {}, got {}" , plugin .getName (), lastRemoved );
176190 }
177191
178192 return true ;
0 commit comments