From e588fd94a83d85d0aed09b8f71b4a9c5ec488425 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 6 Jul 2020 18:38:10 -0400 Subject: [PATCH] Fix Concurrency issue in WeightedList if multiple threads from worldgen sort at same time, it will crash. So make a copy of the list for sorting purposes. Fixes #3732 Fixes #3824 --- ...ix-Concurrency-issue-in-WeightedList.patch | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch diff --git a/Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch new file mode 100644 index 000000000..7279b4f88 --- /dev/null +++ b/Spigot-Server-Patches/0540-Fix-Concurrency-issue-in-WeightedList.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 6 Jul 2020 18:36:41 -0400 +Subject: [PATCH] Fix Concurrency issue in WeightedList + +if multiple threads from worldgen sort at same time, it will crash. +So make a copy of the list for sorting purposes. + +diff --git a/src/main/java/net/minecraft/server/WeightedList.java b/src/main/java/net/minecraft/server/WeightedList.java +index 73e5969b2a15f1639b6285286820e9f7871c7db8..b4e871140e7a0ab5e402e415ea4ff04605157d54 100644 +--- a/src/main/java/net/minecraft/server/WeightedList.java ++++ b/src/main/java/net/minecraft/server/WeightedList.java +@@ -14,7 +14,7 @@ import java.util.stream.Stream; + + public class WeightedList { + +- protected final List> a; ++ protected final List> list; // Paper - decompile conflict + private final Random b; + + public WeightedList() { +@@ -23,17 +23,17 @@ public class WeightedList { + + private WeightedList(List> list) { + this.b = new Random(); +- this.a = Lists.newArrayList(list); ++ this.list = Lists.newArrayList(list); // Paper - decompile conflict + } + + public static Codec> a(Codec codec) { +- return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { +- return weightedlist.a; ++ return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict ++ return weightedlist.list; // Paper - decompile conflict + }); + } + + public WeightedList a(U u0, int i) { +- this.a.add(new WeightedList.a<>(u0, i)); ++ this.list.add(new WeightedList.a<>(u0, i)); // Paper - decompile conflict + return this; + } + +@@ -42,21 +42,20 @@ public class WeightedList { + } + + public WeightedList a(Random random) { +- this.a.forEach((weightedlist_a) -> { +- weightedlist_a.a(random.nextFloat()); +- }); +- this.a.sort(Comparator.comparingDouble((object) -> { +- return ((WeightedList.a) object).c(); +- })); +- return this; ++ // Paper start - make concurrent safe, work off a clone of the list ++ java.util.ArrayList> list = new java.util.ArrayList>(this.list); ++ list.forEach((weightedlist_a) -> weightedlist_a.a(random.nextFloat())); ++ list.sort(Comparator.comparingDouble(a::c)); ++ return new WeightedList<>(list); ++ // Paper end + } + + public boolean b() { +- return this.a.isEmpty(); ++ return this.list.isEmpty(); // Paper - decompile conflict + } + + public Stream c() { +- return this.a.stream().map(WeightedList.a::a); ++ return this.list.stream().map(WeightedList.a::a); // Paper - decompile conflict + } + + public U b(Random random) { +@@ -64,7 +63,7 @@ public class WeightedList { + } + + public String toString() { +- return "WeightedList[" + this.a + "]"; ++ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict + } + + public static class a { +@@ -98,11 +97,7 @@ public class WeightedList { + return new Codec>() { + public DataResult, T>> decode(DynamicOps dynamicops, T t0) { + Dynamic dynamic = new Dynamic(dynamicops, t0); +- OptionalDynamic optionaldynamic = dynamic.get("data"); +- Codec codec1 = codec; +- +- codec.getClass(); +- return optionaldynamic.flatMap(codec1::parse).map((object) -> { ++ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error + return new WeightedList.a<>(object, dynamic.get("weight").asInt(1)); + }).map((weightedlist_a) -> { + return Pair.of(weightedlist_a, dynamicops.empty());