diff --git a/pool/tree/pool.go b/pool/tree/pool.go index ddfdc0e..b77d63a 100644 --- a/pool/tree/pool.go +++ b/pool/tree/pool.go @@ -1009,8 +1009,10 @@ func (p *Pool) addClientToMap(hash uint64, cl client) { func (p *Pool) deleteClientFromMap(hash uint64) { p.mutex.Lock() - _ = p.clientMap[hash].close() - delete(p.clientMap, hash) + if cli, ok := p.clientMap[hash]; ok { + _ = cli.close() + delete(p.clientMap, hash) + } p.mutex.Unlock() } diff --git a/pool/tree/pool_test.go b/pool/tree/pool_test.go index 607e037..5814a77 100644 --- a/pool/tree/pool_test.go +++ b/pool/tree/pool_test.go @@ -10,6 +10,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool" "git.frostfs.info/TrueCloudLab/hrw" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -416,6 +417,21 @@ func TestRetryContainerNodes(t *testing.T) { }) } +func TestDeleteClientTwice(t *testing.T) { + p := Pool{ + clientMap: makeClientMap([]netmap.NodeInfo{netmaptest.NodeInfo()}), + } + // emulate concurrent requests as consecutive requests + // to delete the same client from the map twice + for idToDelete := range p.clientMap { + p.deleteClientFromMap(idToDelete) + require.NotPanics(t, func() { + p.deleteClientFromMap(idToDelete) + }) + } + require.Empty(t, p.clientMap) +} + func makeInnerPool(nodes [][]string) []*innerPool { res := make([]*innerPool, len(nodes))