Patch memory error related to []byte pool

This commit is contained in:
2022-09-28 14:28:37 +02:00
parent 57ba460929
commit ebefa28cc0
5 changed files with 44 additions and 52 deletions

View File

@ -1,26 +0,0 @@
package cutils
import "C"
import (
"reflect"
"unsafe"
)
// ByteSlice builds a byte Slice over a C pointer returned by a
// C function.
// The C pointer has to be passed as an unsafe.Pointer
// and the size of the pointed memery area has to be
// indicated through the size parameter.
// No memory allocation is done by that function. It
// just consists in mapping a Go object too a C one.
func ByteSlice(pointer unsafe.Pointer, size int) []byte {
var s []byte
h := (*reflect.SliceHeader)((unsafe.Pointer(&s)))
h.Cap = size
h.Len = size
h.Data = uintptr(pointer)
return s
}

View File

@ -71,10 +71,10 @@ func _BuildAlignment(seqA, seqB []byte, path []int, gap byte, bufferA, bufferB *
func BuildAlignment(seqA, seqB *obiseq.BioSequence, func BuildAlignment(seqA, seqB *obiseq.BioSequence,
path []int, gap byte) (*obiseq.BioSequence, *obiseq.BioSequence) { path []int, gap byte) (*obiseq.BioSequence, *obiseq.BioSequence) {
bufferSA := obiseq.GetSlice() bufferSA := obiseq.GetSlice(seqA.Length())
defer obiseq.RecycleSlice(&bufferSA) defer obiseq.RecycleSlice(&bufferSA)
bufferSB := obiseq.GetSlice() bufferSB := obiseq.GetSlice(seqB.Length())
defer obiseq.RecycleSlice(&bufferSB) defer obiseq.RecycleSlice(&bufferSB)
_BuildAlignment(seqA.Sequence(), seqB.Sequence(), path, gap, _BuildAlignment(seqA.Sequence(), seqB.Sequence(), path, gap,
@ -115,12 +115,12 @@ func BuildAlignment(seqA, seqB *obiseq.BioSequence,
// return. // return.
func BuildQualityConsensus(seqA, seqB *obiseq.BioSequence, path []int) (*obiseq.BioSequence, int) { func BuildQualityConsensus(seqA, seqB *obiseq.BioSequence, path []int) (*obiseq.BioSequence, int) {
bufferSA := obiseq.GetSlice() bufferSA := obiseq.GetSlice(seqA.Length())
bufferSB := obiseq.GetSlice() bufferSB := obiseq.GetSlice(seqB.Length())
defer obiseq.RecycleSlice(&bufferSB) defer obiseq.RecycleSlice(&bufferSB)
bufferQA := obiseq.GetSlice() bufferQA := obiseq.GetSlice(seqA.Length())
bufferQB := obiseq.GetSlice() bufferQB := obiseq.GetSlice(seqB.Length())
defer obiseq.RecycleSlice(&bufferQB) defer obiseq.RecycleSlice(&bufferQB)
_BuildAlignment(seqA.Sequence(), seqB.Sequence(), path, ' ', _BuildAlignment(seqA.Sequence(), seqB.Sequence(), path, ' ',

View File

@ -13,7 +13,6 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"git.metabarcoding.org/lecasofts/go/obitools/pkg/cutils"
"git.metabarcoding.org/lecasofts/go/obitools/pkg/obiiter" "git.metabarcoding.org/lecasofts/go/obitools/pkg/obiiter"
"git.metabarcoding.org/lecasofts/go/obitools/pkg/obiseq" "git.metabarcoding.org/lecasofts/go/obitools/pkg/obiseq"
) )
@ -31,13 +30,7 @@ func _FastseqReader(seqfile C.fast_kseq_p,
s := seqfile.seq s := seqfile.seq
csequence := cutils.ByteSlice(unsafe.Pointer(s.seq.s), int(s.seq.l)) sequence := C.GoBytes(unsafe.Pointer(s.seq.s), C.int(s.seq.l))
sequence := obiseq.GetSlice()
sequence = append(sequence, csequence...)
//sequence := C.GoBytes(unsafe.Pointer(s.seq.s),
// C.int(s.seq.l))
name := C.GoString(s.name.s) name := C.GoString(s.name.s)
if s.comment.l > C.ulong(0) { if s.comment.l > C.ulong(0) {
@ -49,12 +42,23 @@ func _FastseqReader(seqfile C.fast_kseq_p,
rep := obiseq.NewBioSequence(name, sequence, comment) rep := obiseq.NewBioSequence(name, sequence, comment)
if s.qual.l > C.ulong(0) { if s.qual.l > C.ulong(0) {
cquality := cutils.ByteSlice(unsafe.Pointer(s.qual.s), int(s.qual.l)) cquality := unsafe.Slice(s.qual.s, C.int(s.qual.l))
l := int(s.qual.l) l := int(s.qual.l)
quality := obiseq.GetSlice() quality := obiseq.GetSlice(l)
shift := uint8(seqfile.shift) shift := uint8(seqfile.shift)
for j := 0; j < l; j++ { for j := 0; j < l; j++ {
func() {
defer func() {
if err := recover(); err != nil {
log.Println("cquality:", cquality,
"s.qual.s:", s.qual.s,
"quality:", quality)
log.Panic("panic occurred:", err)
}
}()
quality = append(quality, uint8(cquality[j])-shift) quality = append(quality, uint8(cquality[j])-shift)
}()
} }
rep.SetQualities(quality) rep.SetQualities(quality)

View File

@ -129,9 +129,9 @@ func (s *BioSequence) Copy() *BioSequence {
newSeq.id = s.id newSeq.id = s.id
newSeq.definition = s.definition newSeq.definition = s.definition
newSeq.sequence = GetSlice(s.sequence...) newSeq.sequence = CopySlice(s.sequence)
newSeq.qualities = GetSlice(s.qualities...) newSeq.qualities = CopySlice(s.qualities)
newSeq.feature = GetSlice(s.feature...) newSeq.feature = CopySlice(s.feature)
if len(s.annotations) > 0 { if len(s.annotations) > 0 {
newSeq.annotations = GetAnnotation(s.annotations) newSeq.annotations = GetAnnotation(s.annotations)
@ -340,7 +340,6 @@ func (s *BioSequence) ClearQualities() {
s.qualities = s.qualities[0:0] s.qualities = s.qualities[0:0]
} }
// A method that appends a byte slice to the sequence. // A method that appends a byte slice to the sequence.
func (s *BioSequence) Write(data []byte) (int, error) { func (s *BioSequence) Write(data []byte) (int, error) {
s.sequence = append(s.sequence, data...) s.sequence = append(s.sequence, data...)

View File

@ -1,6 +1,7 @@
package obiseq package obiseq
import ( import (
"log"
"sync" "sync"
"git.metabarcoding.org/lecasofts/go/obitools/pkg/goutils" "git.metabarcoding.org/lecasofts/go/obitools/pkg/goutils"
@ -14,22 +15,36 @@ var _BioSequenceByteSlicePool = sync.Pool{
} }
func RecycleSlice(s *[]byte) { func RecycleSlice(s *[]byte) {
if s != nil && *s != nil { if s != nil && cap(*s) > 0 {
*s = (*s)[:0] *s = (*s)[:0]
if cap(*s) == 0 {
log.Panicln("trying to store a NIL slice in the pool", s == nil, *s == nil, cap(*s))
}
_BioSequenceByteSlicePool.Put(s) _BioSequenceByteSlicePool.Put(s)
} }
} }
func GetSlice(values ...byte) []byte { // It returns a slice of bytes from a pool of slices.
s := *(_BioSequenceByteSlicePool.Get().(*[]byte)) //
// the slice can be prefilled with the provided values
func GetSlice(capacity int) []byte {
p := _BioSequenceByteSlicePool.Get().(*[]byte)
if len(values) > 0 { if p == nil || *p == nil || cap(*p) < capacity {
s = append(s, values...) s := make([]byte, 0, capacity)
p = &s
} }
s := *p
return s return s
} }
func CopySlice(src []byte) []byte {
sl := GetSlice(len(src))
copy(sl,src)
return sl
}
var BioSequenceAnnotationPool = sync.Pool{ var BioSequenceAnnotationPool = sync.Pool{
New: func() interface{} { New: func() interface{} {
bs := make(Annotation, 5) bs := make(Annotation, 5)