From 80ee619035f13c1f2e0cbacf958064dde04c80ee Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 16 Sep 2018 02:57:22 -0400 Subject: [PATCH] prevent crashes on expiring map desync, dont spam logs --- ...ix-major-memory-leaks-in-ExpiringMap.patch | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/Spigot-Server-Patches/0372-Fix-major-memory-leaks-in-ExpiringMap.patch b/Spigot-Server-Patches/0372-Fix-major-memory-leaks-in-ExpiringMap.patch index 8e48f83399..892133dd16 100644 --- a/Spigot-Server-Patches/0372-Fix-major-memory-leaks-in-ExpiringMap.patch +++ b/Spigot-Server-Patches/0372-Fix-major-memory-leaks-in-ExpiringMap.patch @@ -1,4 +1,4 @@ -From 6a439506b07605dd8566c86b672d3ee955715b51 Mon Sep 17 00:00:00 2001 +From 36d303e9b7046708890efc99f68d8dbab88ce4ac Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 16 Sep 2018 00:00:16 -0400 Subject: [PATCH] Fix major memory leaks in ExpiringMap @@ -11,10 +11,10 @@ not run on every manipulation, and instead to run clean once per tick per expiring map. diff --git a/src/main/java/net/minecraft/server/ExpiringMap.java b/src/main/java/net/minecraft/server/ExpiringMap.java -index 4006f5a69c..49021d29ee 100644 +index 4006f5a69c..08d41e8cf0 100644 --- a/src/main/java/net/minecraft/server/ExpiringMap.java +++ b/src/main/java/net/minecraft/server/ExpiringMap.java -@@ -6,25 +6,113 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +@@ -6,25 +6,120 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2LongMap.Entry; import it.unimi.dsi.fastutil.objects.ObjectIterator; import java.util.Map; @@ -116,10 +116,17 @@ index 4006f5a69c..49021d29ee 100644 + @Override + public T compute(Long aLong, BiFunction biFunction) { + setAccess(aLong); -+ return compute(aLong, biFunction); ++ return super.compute(aLong, biFunction); ++ } ++ ++ @Override ++ public synchronized void clear() { ++ ttl.clear(); ++ super.clear(); + } + + private boolean registered = false; ++ private boolean hasLeaked = false; + + // Break clean to its own method to be ticked + synchronized boolean clean() { @@ -136,16 +143,23 @@ index 4006f5a69c..49021d29ee 100644 break; } -@@ -33,7 +121,18 @@ public class ExpiringMap extends Long2ObjectOpenHashMap { +@@ -33,7 +128,25 @@ public class ExpiringMap extends Long2ObjectOpenHashMap { objectiterator.remove(); } } - -+ if (this.ttl.size() != this.size()) { -+ MinecraftServer.LOGGER.error("WARNING: ExpiringMap desync - Memory leak risk!"); -+ for (Entry entry : this.long2ObjectEntrySet()) { -+ ttl.putIfAbsent(entry.getLongKey(), now); ++ int ttlSize = this.ttl.size(); ++ int thisSize = this.size(); ++ if (ttlSize != thisSize) { ++ if (!hasLeaked) { // log once ++ hasLeaked = true; ++ MinecraftServer.LOGGER.warn("WARNING: ExpiringMap desync (" + ttlSize + ":" + thisSize + ")- Memory leak risk! We will recover from this, but this means there is still a bug. Please do not open an issue about this. Mention it in Discord (we don't need everyone reporting the same thing)"); + } ++ try { ++ for (Entry entry : this.long2ObjectEntrySet()) { ++ ttl.putIfAbsent(entry.getLongKey(), now); ++ } ++ } catch (Exception e) { } // Ignore any como's + } + if (isEmpty()) { + registered = false;