diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 739c17f63..02a3f7f8b 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -195,7 +195,14 @@ func storageFind(ic *interop.Context) error { seekres := ic.DAO.SeekAsync(ctx, stc.ID, storage.SeekRange{Prefix: prefix}) item := istorage.NewIterator(seekres, prefix, opts) ic.VM.Estack().PushItem(stackitem.NewInterop(item)) - ic.RegisterCancelFunc(cancel) + ic.RegisterCancelFunc(func() { + cancel() + // Underlying persistent store is likely to be a private MemCachedStore. Thus, + // to avoid concurrent map iteration and map write we need to wait until internal + // seek goroutine is finished, because it can access underlying persistent store. + for range seekres { + } + }) return nil } diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 606c0a0cd..335b99b25 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -969,7 +969,11 @@ func (n *NEO) getAllCandidatesCall(ic *interop.Context, _ []stackitem.Item) stac opts := istorage.FindRemovePrefix | istorage.FindDeserialize | istorage.FindPick1 item := istorage.NewIterator(filteredRes, prefix, int64(opts)) - ic.RegisterCancelFunc(cancel) + ic.RegisterCancelFunc(func() { + cancel() + for range seekres { + } + }) return stackitem.NewInterop(item) }