mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Bugfix: unsafeBytes slices were getting GCed (#913)
There are alternative formulations of this, for instance see https://www.reddit.com/r/golang/comments/5zctpf/unsafe_conversion_between_strings_and_byte_slices/ The problem manifested in the returned values from unsafeBytes occasionally being broken. It's possible that by keeping a reference to the `a` parameter alive, the original code would still work - however, this definitely seems like a fix. (A cast to `[]byte(a)` looks increasingly attractive, for all that it'll perform small allocations and copies.)
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"hash"
|
"hash"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -332,5 +333,17 @@ func getSlotQueueKey(call *call) string {
|
|||||||
|
|
||||||
// WARN: this is read only
|
// WARN: this is read only
|
||||||
func unsafeBytes(a string) []byte {
|
func unsafeBytes(a string) []byte {
|
||||||
return *(*[]byte)(unsafe.Pointer(&a))
|
strHeader := (*reflect.StringHeader)(unsafe.Pointer(&a))
|
||||||
|
|
||||||
|
var b []byte
|
||||||
|
byteHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||||
|
byteHeader.Data = strHeader.Data
|
||||||
|
|
||||||
|
// need to take the length of `a` here to ensure it's alive until after we update b's Data
|
||||||
|
// field since the garbage collector can collect a variable once it is no longer used
|
||||||
|
// not when it goes out of scope, for more details see https://github.com/golang/go/issues/9046
|
||||||
|
l := len(a)
|
||||||
|
byteHeader.Len = l
|
||||||
|
byteHeader.Cap = l
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user