-
commitID:ce292e9814b7c0fbcbdb586c7705eaf304edc599
-
文件:life/exec/mem_pool.go
-
问题描述:
type MemPool struct {
sync.Mutex
memBlock []*MemBlock
largeMem map[int]*sync.Pool
}
内存池的memblock字段用来做内存的预先分配,用的数据结构是slice,没有对这个slice进行数据竞争的管理,在多线程同时申请内存时(运行wasm合约),会引起不可预知的错误。
虽然每个block的tx是串行的,但是外部用户可以通过rpc请求节点,做查询操作,这个时候就会出现多个wasm并行问题。
以下代码是对memBlock字段的访问,可以看到没有做任何的数据竞争管理。
func (mp *MemPool) Get(pages int) []byte {
mp.Lock()
defer mp.Unlock()
if pages <= 0 {
return nil
}
var mem []byte
pages = fixSize(pages - DefaultMemoryPages)
pos := int(math.Log2(float64(pages)))
if pos >= len(mp.memBlock) {
pool, ok := mp.largeMem[pages]
if !ok {
pool = &sync.Pool{
New: func() interface{} {
return make([]byte, DefaultPageSize*(pages+DefaultMemoryPages))
},
}
mp.largeMem[pages] = pool
}
mem = pool.Get().([]byte)
} else {
mem = mp.memBlock[pos].Get()
}
memset(mem)
return mem
}
func (mp *MemPool) Put(mem []byte) {
mp.Lock()
defer mp.Unlock()
pages := len(mem) / DefaultPageSize
pages = fixSize(pages - DefaultMemoryPages)
pos := int(math.Log2(float64(pages)))
if pos >= len(mp.memBlock) {
pool, ok := mp.largeMem[pages]
if !ok {
return
}
pool.Put(mem)
} else {
mp.memBlock[pos].Put(mem)
}
}