From f100381167c0082aae3b42cfad293cc79e4c6f8d Mon Sep 17 00:00:00 2001 From: soffokl Date: Fri, 5 Apr 2024 13:48:38 +0600 Subject: [PATCH] Fix concurrent map read and map write fatal error: concurrent map read and map write goroutine 1237208 [running]: github.com/mysteriumnetwork/node/session/pingpong.(*ConsumerTotalsStorage).Store(0xc000e042a0, 0x89, {{0xc004cc8270?, 0x13?}}, {0x80, 0xed, 0x28, 0xd8, 0x47, 0x92, ...}, ...) /go/src/github.com/mysteriumnetwork/node/session/pingpong/consumer_totals_storage.go:56 +0xbc github.com/mysteriumnetwork/node/session/pingpong.(*ConsumerBalanceTracker).recoverGrandTotalPromised(0xc000ffa000, 0x89, {{0xc004cc8270?, 0xc00074be20?}}) /go/src/github.com/mysteriumnetwork/node/session/pingpong/consumer_balance_tracker.go:688 +0x5ef github.com/mysteriumnetwork/node/session/pingpong.(*ConsumerBalanceTracker).handleUnlockEvent(0xc000ffa000, {0x0?, {{0xc004cc8270?, 0x0?}}}) /go/src/github.com/mysteriumnetwork/node/session/pingpong/consumer_balance_tracker.go:250 +0x36 reflect.Value.call({0x16e3cc0?, 0xc00053cba0?, 0x84dad1?}, {0x1a178fb, 0x4}, {0xc00745d158, 0x1, 0x0?}) /usr/local/go/src/reflect/value.go:586 +0xb07 reflect.Value.Call({0x16e3cc0?, 0xc00053cba0?, 0xc006edfbd0?}, {0xc00745d158?, 0xc002e5d840?, 0x40?}) /usr/local/go/src/reflect/value.go:370 +0xbc github.com/mysteriumnetwork/EventBus.(*EventBus).doPublish(0xc000e041c0, 0xc000c11830, {0x1aee427, 0x11}, {0xc006edfbd0?, 0x240bc20?, 0xc0045e6fb8?}) /go/pkg/mod/github.com/mysteriumnetwork/!event!bus@v0.0.0-20220415063055-d22cb121672c/event_bus.go:155 +0xf6 github.com/mysteriumnetwork/EventBus.(*EventBus).doPublishAsync(0xc00519c728?, 0x443445?, {0x1aee427?, 0xc0045e6fa0?}, {0xc006edfbd0?, 0xcb7d66?, 0xc00519c700?}) /go/pkg/mod/github.com/mysteriumnetwork/!event!bus@v0.0.0-20220415063055-d22cb121672c/event_bus.go:177 +0xa5 created by github.com/mysteriumnetwork/EventBus.(*EventBus).Publish /go/pkg/mod/github.com/mysteriumnetwork/!event!bus@v0.0.0-20220415063055-d22cb121672c/event_bus.go:147 +0x232 --- session/pingpong/consumer_totals_storage.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/session/pingpong/consumer_totals_storage.go b/session/pingpong/consumer_totals_storage.go index dd035af7b9..4963fa243f 100644 --- a/session/pingpong/consumer_totals_storage.go +++ b/session/pingpong/consumer_totals_storage.go @@ -23,15 +23,16 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" + "github.com/rs/zerolog/log" + "github.com/mysteriumnetwork/node/eventbus" "github.com/mysteriumnetwork/node/identity" "github.com/mysteriumnetwork/node/session/pingpong/event" - "github.com/rs/zerolog/log" ) // ConsumerTotalsStorage allows to store total promised amounts for each channel. type ConsumerTotalsStorage struct { - createLock sync.Mutex + createLock sync.RWMutex bus eventbus.Publisher data map[string]*ConsumerTotalElement } @@ -52,17 +53,18 @@ func NewConsumerTotalsStorage(bus eventbus.Publisher) *ConsumerTotalsStorage { // Store stores the given amount as promised for the given channel. func (cts *ConsumerTotalsStorage) Store(chainID int64, id identity.Identity, hermesID common.Address, amount *big.Int) error { + cts.createLock.Lock() + defer cts.createLock.Unlock() + key := cts.makeKey(chainID, id, hermesID) _, ok := cts.data[key] if !ok { - cts.createLock.Lock() _, ok := cts.data[key] if !ok { cts.data[key] = &ConsumerTotalElement{ amount: nil, } } - cts.createLock.Unlock() } element, ok := cts.data[key] if !ok { @@ -94,8 +96,8 @@ func (cts *ConsumerTotalsStorage) Store(chainID int64, id identity.Identity, her // Get fetches the amount as promised for the given channel. func (cts *ConsumerTotalsStorage) Get(chainID int64, id identity.Identity, hermesID common.Address) (*big.Int, error) { key := cts.makeKey(chainID, id, hermesID) - cts.createLock.Lock() - defer cts.createLock.Unlock() + cts.createLock.RLock() + defer cts.createLock.RUnlock() element, ok := cts.data[key] if !ok { @@ -112,17 +114,18 @@ func (cts *ConsumerTotalsStorage) Get(chainID int64, id identity.Identity, herme // Add adds the given amount as promised for the given channel. func (cts *ConsumerTotalsStorage) Add(chainID int64, id identity.Identity, hermesID common.Address, amount *big.Int) error { + cts.createLock.Lock() + defer cts.createLock.Unlock() + key := cts.makeKey(chainID, id, hermesID) _, ok := cts.data[key] if !ok { - cts.createLock.Lock() _, ok := cts.data[key] if !ok { cts.data[key] = &ConsumerTotalElement{ amount: nil, } } - cts.createLock.Unlock() } element, ok := cts.data[key] if !ok {