Skip to content

Commit 24ba349

Browse files
authored
fix potential concurrent modification exception in PendingPool (#7813)
1 parent 9b529f1 commit 24ba349

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/util/PendingPool.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public synchronized void add(T item) {
9797

9898
final Bytes32 itemRoot = hashTreeRootFunction.apply(item);
9999
final Collection<Bytes32> requiredRoots = requiredBlockRootsFunction.apply(item);
100+
final ArrayList<Bytes32> newRequiredRoots = new ArrayList<>();
100101

101102
requiredRoots.forEach(
102103
requiredRoot ->
@@ -106,12 +107,15 @@ public synchronized void add(T item) {
106107
requiredRoot,
107108
(key) -> {
108109
final Set<Bytes32> dependants = new HashSet<>();
109-
requiredBlockRootSubscribers.forEach(
110-
c -> c.onRequiredBlockRoot(requiredRoot));
110+
newRequiredRoots.add(requiredRoot);
111111
return dependants;
112112
})
113113
.add(itemRoot));
114114

115+
newRequiredRoots.forEach(
116+
requiredRoot ->
117+
requiredBlockRootSubscribers.forEach(s -> s.onRequiredBlockRoot(requiredRoot)));
118+
115119
// Index item by root
116120
if (pendingItems.putIfAbsent(itemRoot, item) == null) {
117121
LOG.trace(

ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/util/PendingPoolTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,25 @@ private void setSlot(final UInt64 slot) {
5959
pendingPool.onSlot(slot);
6060
}
6161

62+
@Test
63+
public void add_shouldDeferSubscribersCallToAvoidConcurrentModificationException() {
64+
final SignedBeaconBlock block =
65+
dataStructureUtil.randomSignedBeaconBlock(currentSlot.longValue());
66+
67+
final SignedBeaconBlock block2 =
68+
dataStructureUtil.randomSignedBeaconBlock(currentSlot.longValue());
69+
70+
pendingPool.subscribeRequiredBlockRoot(
71+
blockRoot -> {
72+
if (blockRoot.equals(block.getParentRoot())) {
73+
pendingPool.add(block2);
74+
}
75+
});
76+
pendingPool.add(block);
77+
78+
assertThat(pendingPool.contains(block2)).isTrue();
79+
}
80+
6281
@Test
6382
public void add_blockForCurrentSlot() {
6483
final SignedBeaconBlock block =

0 commit comments

Comments
 (0)