Safely handle race condition between isEmpty() and lastKey() being called (#8362)

* Safely handle race condition between isEmpty() and lastKey() being called

Signed-off-by: Matthew Whitehead <matthew1001@gmail.com>

* Fix not needed in AbstractTransactionsLayer

Signed-off-by: Matthew Whitehead <matthew1001@gmail.com>

* Reinstate final modifier

Signed-off-by: Matthew Whitehead <matthew1001@gmail.com>

---------

Signed-off-by: Matthew Whitehead <matthew1001@gmail.com>
This commit is contained in:
Matt Whitehead
2025-03-04 10:46:15 +00:00
committed by GitHub
parent 74a1d8a1ea
commit 46765cdd02

View File

@@ -20,6 +20,7 @@ import org.hyperledger.besu.evm.account.Account;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.TreeMap;
@@ -96,7 +97,15 @@ public class PendingTransactionsForSender {
if (pendingTransactions.isEmpty()) {
return OptionalLong.empty();
} else {
return nextGap.isEmpty() ? OptionalLong.of(pendingTransactions.lastKey() + 1) : nextGap;
try {
return nextGap.isEmpty() ? OptionalLong.of(pendingTransactions.lastKey() + 1) : nextGap;
} catch (NoSuchElementException nse) {
// There is a timing condition where isEmpty() returns false, then another thread removes
// the last key before our call to lastKey(). There's no benefit to us adding a mutex to
// prevent the other thread updating the map so we just catch the exception and treat the
// map as empty.
return OptionalLong.empty();
}
}
}