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/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/micro/go-micro/store"
|
"github.com/micro/go-micro/store"
|
||||||
ckv "github.com/micro/go-micro/store/etcd"
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort.Slice(keyvals, func(i, j int) bool {
|
||||||
|
return keyvals[i].Key < keyvals[j].Key
|
||||||
|
})
|
||||||
|
|
||||||
for _, keyval := range keyvals {
|
for _, keyval := range keyvals {
|
||||||
// lock
|
// lock
|
||||||
if err := m.opts.Lock.Acquire(keyval.Key); err != nil {
|
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