Here's a test script I've been using:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"os"
"sync"
fdb "github.com/couchbaselabs/goforestdb"
)
var testFile = "/tmp/test.fdb"
var testValue = bytes.Repeat([]byte{120}, 256)
var total = int(1e5)
func abortOn(err error) {
if err != nil {
log.Fatal(err.Error())
}
}
func main() {
os.RemoveAll(testFile)
config := fdb.DefaultConfig()
config.SetWalFlushBeforeCommit(true)
wg := sync.WaitGroup{}
db, err := fdb.Open(testFile, config)
abortOn(err)
defer db.Close()
abortOn(write(db, 0))
abortOn(read(db, 0))
wg.Add(1)
go func() {
defer wg.Done()
abortOn(write(db, 1))
}()
wg.Add(1)
go func() {
defer wg.Done()
abortOn(read(db, 0))
}()
wg.Wait()
}
func write(db *fdb.Database, base int) error {
fmt.Println("* writing")
for n := 0; n < total; n++ {
key := make([]byte, 4)
binary.BigEndian.PutUint32(key, uint32(base*total+n))
if err := db.SetKV(key, testValue); err != nil {
return err
}
}
return db.Commit(fdb.COMMIT_NORMAL)
}
func read(db *fdb.Database, base int) error {
fmt.Println("* reading")
for n := 0; n < total; n++ {
key := make([]byte, 4)
binary.BigEndian.PutUint32(key, uint32(base*total+n))
if _, err := db.GetKV(key); err != nil {
return err
}
}
return nil
}
Causes:
$ go run fdb-bug.go
* writing
* reading
* writing
* reading
*** Error in `/tmp/go-build726603444/command-line-arguments/_obj/exe/fdb-bug': double free or corruption (fasttop): 0x00000000097f6e00 ***
SIGABRT: abort
PC=0x7f1172a0ad27
signal arrived during cgo execution
goroutine 21 [syscall]:
runtime.cgocall(0x402410, 0x7f1173239e08)
$GOROOT/src/pkg/runtime/cgocall.c:143 +0xe5 fp=0x7f1173239df0 sp=0x7f1173239da8
github.com/couchbaselabs/goforestdb._Cfunc_fdb_get_kv(0x13b62c0, 0xc208073040, 0x4, 0xc20803c758, 0xc208073048, 0x1)
github.com/couchbaselabs/goforestdb/_obj/_cgo_defun.c:179 +0x31 fp=0x7f1173239e08 sp=0x7f1173239df0
github.com/couchbaselabs/goforestdb.(*Database).GetKV(0xc20803c028, 0xc208073040, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0)
$GOPATH/src/github.com/couchbaselabs/goforestdb/kv.go:32 +0xf2 fp=0x7f1173239e88 sp=0x7f1173239e08
main.read(0xc20803c028, 0x0, 0x0, 0x0)
fdb-bug.go:68 +0x1ee fp=0x7f1173239f68 sp=0x7f1173239e88
main.funcĀ·002()
fdb-bug.go:45 +0x58 fp=0x7f1173239fa8 sp=0x7f1173239f68
runtime.goexit()
$GOROOT/src/pkg/runtime/proc.c:1445 fp=0x7f1173239fb0 sp=0x7f1173239fa8
created by main.main
fdb-bug.go:46 +0x23d
goroutine 16 [semacquire]:
sync.runtime_Semacquire(0xc208096e50)
$GOROOT/src/pkg/runtime/sema.goc:199 +0x30
sync.(*WaitGroup).Wait(0xc20805a000)
$GOROOT/src/pkg/sync/waitgroup.go:129 +0x14b
main.main()
fdb-bug.go:47 +0x24d
goroutine 19 [finalizer wait]:
runtime.park(0x4153f0, 0x77bbd8, 0x770de9)
$GOROOT/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x77bbd8, 0x770de9)
$GOROOT/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
$GOROOT/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
$GOROOT/src/pkg/runtime/proc.c:1445
goroutine 17 [syscall]:
runtime.goexit()
$GOROOT/src/pkg/runtime/proc.c:1445
goroutine 20 [syscall]:
github.com/couchbaselabs/goforestdb._Cfunc_fdb_set_kv(0x13b62c0, 0xc208073020, 0x4, 0xc208040000, 0x100, 0x425de3)
github.com/couchbaselabs/goforestdb/_obj/_cgo_defun.c:305 +0x31
github.com/couchbaselabs/goforestdb.(*Database).SetKV(0xc20803c028, 0xc208073020, 0x4, 0x4, 0xc208040000, 0x100, 0x100, 0x0, 0x0)
$GOPATH/src/github.com/couchbaselabs/goforestdb/kv.go:58 +0xa4
main.write(0xc20803c028, 0x1, 0x0, 0x0)
fdb-bug.go:55 +0x215
main.funcĀ·001()
fdb-bug.go:40 +0x58
created by main.main
fdb-bug.go:41 +0x1f0
rax 0x0
rbx 0x8b
rcx 0xffffffffffffffff
rdx 0x6
rdi 0x74ef
rsi 0x74f2
rbp 0x7f1170e9ebe0
rsp 0x7f1170e9e848
r8 0x3030653666373930
r9 0x6f6974707572726f
r10 0x8
r11 0x202
r12 0x7f1170e9e9f0
r13 0x7
r14 0x8b
r15 0x7
rip 0x7f1172a0ad27
rflags 0x202
cs 0x33
fs 0x0
gs 0x0
exit status 2
godep: go exit status 1