Fix remaining data race in BurningManAccountingStore

Add missing synchronisation to the 'toProtoMessage' method, by first
copying the internal list of blocks inside a read-lock, prior to
serialisation (still outside the lock, to maximise concurrency). Since
we only make a shallow copy, this should be fast and take no more than a
MB or so of extra memory.

This prevents a race seen to cause a ConcurrentModificationException
during store persistence, that sometimes occurred when the application
resumed from a long suspension.
This commit is contained in:
Steven Barclay 2024-02-24 11:12:33 +08:00
parent 2b4fb78d99
commit 02ee5bc6ea
No known key found for this signature in database
GPG Key ID: 9FED6BF1176D500B

View File

@ -17,7 +17,6 @@
package bisq.core.dao.burningman.accounting.storage;
import bisq.core.dao.burningman.accounting.blockchain.AccountingBlock;
import bisq.core.dao.burningman.accounting.exceptions.BlockHashNotConnectingException;
import bisq.core.dao.burningman.accounting.exceptions.BlockHeightNotConnectingException;
@ -160,9 +159,17 @@ public class BurningManAccountingStore implements PersistableEnvelope {
}
public Message toProtoMessage() {
List<AccountingBlock> blocksCopy;
Lock readLock = readWriteLock.readLock();
readLock.lock();
try {
blocksCopy = new ArrayList<>(blocks);
} finally {
readLock.unlock();
}
return protobuf.PersistableEnvelope.newBuilder()
.setBurningManAccountingStore(protobuf.BurningManAccountingStore.newBuilder()
.addAllBlocks(blocks.stream()
.addAllBlocks(blocksCopy.stream()
.map(AccountingBlock::toProtoMessage)
.collect(Collectors.toList())))
.build();