handles: do not store handles by uintptr
If we store values by uintptrs the GC may try to inspect their values when it kicks in. As the pointers are most likely invalid, this will result in an invalid pointer dereference, causing the program to panic. We can fix this by storing values by an int index value instead, returning pointers to those indices as handles instead.
This commit is contained in:
parent
d95932c84a
commit
1bd338af5e
18
handles.go
18
handles.go
|
@ -11,23 +11,23 @@ type HandleList struct {
|
||||||
// stores the Go pointers
|
// stores the Go pointers
|
||||||
handles []interface{}
|
handles []interface{}
|
||||||
// indicates which indices are in use
|
// indicates which indices are in use
|
||||||
set map[uintptr]bool
|
set map[int]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandleList() *HandleList {
|
func NewHandleList() *HandleList {
|
||||||
return &HandleList{
|
return &HandleList{
|
||||||
handles: make([]interface{}, 5),
|
handles: make([]interface{}, 5),
|
||||||
set: make(map[uintptr]bool),
|
set: make(map[int]bool),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// findUnusedSlot finds the smallest-index empty space in our
|
// findUnusedSlot finds the smallest-index empty space in our
|
||||||
// list. You must only run this function while holding a write lock.
|
// list. You must only run this function while holding a write lock.
|
||||||
func (v *HandleList) findUnusedSlot() uintptr {
|
func (v *HandleList) findUnusedSlot() int {
|
||||||
for i := 1; i < len(v.handles); i++ {
|
for i := 1; i < len(v.handles); i++ {
|
||||||
isUsed := v.set[uintptr(i)]
|
isUsed := v.set[i]
|
||||||
if !isUsed {
|
if !isUsed {
|
||||||
return uintptr(i)
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ func (v *HandleList) findUnusedSlot() uintptr {
|
||||||
slot := len(v.handles)
|
slot := len(v.handles)
|
||||||
v.handles = append(v.handles, nil)
|
v.handles = append(v.handles, nil)
|
||||||
|
|
||||||
return uintptr(slot)
|
return slot
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track adds the given pointer to the list of pointers to track and
|
// Track adds the given pointer to the list of pointers to track and
|
||||||
|
@ -51,12 +51,12 @@ func (v *HandleList) Track(pointer interface{}) unsafe.Pointer {
|
||||||
|
|
||||||
v.Unlock()
|
v.Unlock()
|
||||||
|
|
||||||
return unsafe.Pointer(slot)
|
return unsafe.Pointer(&slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Untrack stops tracking the pointer given by the handle
|
// Untrack stops tracking the pointer given by the handle
|
||||||
func (v *HandleList) Untrack(handle unsafe.Pointer) {
|
func (v *HandleList) Untrack(handle unsafe.Pointer) {
|
||||||
slot := uintptr(handle)
|
slot := *(*int)(handle)
|
||||||
|
|
||||||
v.Lock()
|
v.Lock()
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ func (v *HandleList) Untrack(handle unsafe.Pointer) {
|
||||||
|
|
||||||
// Get retrieves the pointer from the given handle
|
// Get retrieves the pointer from the given handle
|
||||||
func (v *HandleList) Get(handle unsafe.Pointer) interface{} {
|
func (v *HandleList) Get(handle unsafe.Pointer) interface{} {
|
||||||
slot := uintptr(handle)
|
slot := *(*int)(handle)
|
||||||
|
|
||||||
v.RLock()
|
v.RLock()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue