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:
jan grant
2018-04-03 16:53:02 +01:00
committed by GitHub
parent 28edd1779f
commit 9633cf022b

View File

@@ -5,6 +5,7 @@ import (
"crypto/sha1"
"encoding/binary"
"hash"
"reflect"
"sort"
"sync"
"sync/atomic"
@@ -332,5 +333,17 @@ func getSlotQueueKey(call *call) string {
// WARN: this is read only
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
}