[#1444] config: Fix data race on morph component init

It could be called for every shard on metabase resync concurrently and
it is possible to get state with initialized client but not initialized
contract hashes.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2024-10-23 10:39:19 +03:00
parent 8b6ec57c61
commit e515dd4582
Signed by: dstepanov-yadro
GPG key ID: 237AF1A763293BC0
4 changed files with 13 additions and 11 deletions

View file

@ -13,9 +13,7 @@ import (
) )
func initAccountingService(ctx context.Context, c *cfg) { func initAccountingService(ctx context.Context, c *cfg) {
if c.cfgMorph.client == nil { c.initMorphComponents(ctx)
initMorphComponents(ctx, c)
}
balanceMorphWrapper, err := balance.NewFromMorph(c.cfgMorph.client, c.cfgAccounting.scriptHash, 0) balanceMorphWrapper, err := balance.NewFromMorph(c.cfgMorph.client, c.cfgAccounting.scriptHash, 0)
fatalOnErr(err) fatalOnErr(err)

View file

@ -575,6 +575,9 @@ func (c *cfgGRPC) dropConnection(endpoint string) {
} }
type cfgMorph struct { type cfgMorph struct {
initialized bool
guard sync.Mutex
client *client.Client client *client.Client
notaryEnabled bool notaryEnabled bool
@ -1455,10 +1458,7 @@ func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker {
func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider { func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider {
return container.NewInfoProvider(func() (container.Source, error) { return container.NewInfoProvider(func() (container.Source, error) {
// threadsafe: called on init or on sighup when morph initialized c.initMorphComponents(ctx)
if c.cfgMorph.client == nil {
initMorphComponents(ctx, c)
}
cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, containerClient.TryNotary()) cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, containerClient.TryNotary())
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -28,7 +28,12 @@ const (
notaryDepositRetriesAmount = 300 notaryDepositRetriesAmount = 300
) )
func initMorphComponents(ctx context.Context, c *cfg) { func (c *cfg) initMorphComponents(ctx context.Context) {
c.cfgMorph.guard.Lock()
defer c.cfgMorph.guard.Unlock()
if c.cfgMorph.initialized {
return
}
initMorphClient(ctx, c) initMorphClient(ctx, c)
lookupScriptHashesInNNS(c) // smart contract auto negotiation lookupScriptHashesInNNS(c) // smart contract auto negotiation
@ -70,6 +75,7 @@ func initMorphComponents(ctx context.Context, c *cfg) {
c.netMapSource = netmapSource c.netMapSource = netmapSource
c.cfgNetmap.wrapper = wrap c.cfgNetmap.wrapper = wrap
c.cfgMorph.initialized = true
} }
func initMorphClient(ctx context.Context, c *cfg) { func initMorphClient(ctx context.Context, c *cfg) {

View file

@ -143,9 +143,7 @@ func initNetmapService(ctx context.Context, c *cfg) {
parseAttributes(c) parseAttributes(c)
c.cfgNodeInfo.localInfo.SetStatus(netmapSDK.Offline) c.cfgNodeInfo.localInfo.SetStatus(netmapSDK.Offline)
if c.cfgMorph.client == nil { c.initMorphComponents(ctx)
initMorphComponents(ctx, c)
}
initNetmapState(c) initNetmapState(c)