avoid deadlock in syncMap.Iterate (#909)
Previously, when syncMap iterates a list of records which have the same content in different order, a deadlock might happen. By enforcing a certain order, the deadlock can be avoided.
This commit is contained in:
parent
bd37e67839
commit
8579c8b321
@ -5,6 +5,7 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/micro/go-micro/store"
|
||||
ckv "github.com/micro/go-micro/store/etcd"
|
||||
@ -94,6 +95,10 @@ func (m *syncMap) Iterate(fn func(key, val interface{}) error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
sort.Slice(keyvals, func(i, j int) bool {
|
||||
return keyvals[i].Key < keyvals[j].Key
|
||||
})
|
||||
|
||||
for _, keyval := range keyvals {
|
||||
// lock
|
||||
if err := m.opts.Lock.Acquire(keyval.Key); err != nil {
|
||||
|
39
sync/map_test.go
Normal file
39
sync/map_test.go
Normal file
@ -0,0 +1,39 @@
|
||||
package sync
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
store "github.com/micro/go-micro/store"
|
||||
mem_store "github.com/micro/go-micro/store/memory"
|
||||
mem_lock "github.com/micro/go-micro/sync/lock/memory"
|
||||
)
|
||||
|
||||
func TestIterate(t *testing.T) {
|
||||
s1 := mem_store.NewStore()
|
||||
s2 := mem_store.NewStore()
|
||||
recA := &store.Record{
|
||||
Key: "A",
|
||||
Value: nil,
|
||||
}
|
||||
recB := &store.Record{
|
||||
Key: "B",
|
||||
Value: nil,
|
||||
}
|
||||
s1.Write(recA)
|
||||
s1.Write(recB)
|
||||
s2.Write(recB)
|
||||
s2.Write(recA)
|
||||
|
||||
f := func(key, val interface{}) error {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
return nil
|
||||
}
|
||||
l := mem_lock.NewLock()
|
||||
m1 := NewMap(WithStore(s1), WithLock(l))
|
||||
m2 := NewMap(WithStore(s2), WithLock(l))
|
||||
go func() {
|
||||
m2.Iterate(f)
|
||||
}()
|
||||
m1.Iterate(f)
|
||||
}
|
Loading…
Reference in New Issue
Block a user