boltdb/bolt

SIGSEGV when running benchmark test

patrobinson opened this issue · 2 comments

When executing an Update() within a benchmark test we receive a SIGSEGV

Environment

Go: 1.8.1
OS: darwin
BoltDB: v1.3.1 2f1ce7a

Stack trace

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x1c0 pc=0x10f9e71]

goroutine 21 [running]:
github.com/boltdb/bolt.(*DB).beginRWTx(0x0, 0x0, 0x0, 0x0)
	/Users/patrickrobinson/go/src/github.com/boltdb/bolt/db.go:506 +0x41
github.com/boltdb/bolt.(*DB).Begin(0x0, 0x11de001, 0x1, 0x8, 0x4d0)
	/Users/patrickrobinson/go/src/github.com/boltdb/bolt/db.go:461 +0x38
github.com/boltdb/bolt.(*DB).Update(0x0, 0xc4200fcf00, 0x0, 0x0)
	/Users/patrickrobinson/go/src/github.com/boltdb/bolt/db.go:582 +0x46
github.com/patrobinson/replicate-boltdb-bug.setUp()
	/Users/patrickrobinson/go/src/github.com/patrobinson/replicate-boltdb-bug/main.go:19 +0xf1
github.com/patrobinson/replicate-boltdb-bug.BenchmarkRun(0xc4200c0000)
	/Users/patrickrobinson/go/src/github.com/patrobinson/replicate-boltdb-bug/main_test.go:6 +0x22
testing.(*B).runN(0xc4200c0000, 0x64)
	/usr/local/Cellar/go/1.8.3/libexec/src/testing/benchmark.go:140 +0xb2
testing.(*B).launch(0xc4200c0000)
	/usr/local/Cellar/go/1.8.3/libexec/src/testing/benchmark.go:281 +0x122
created by testing.(*B).doBench
	/usr/local/Cellar/go/1.8.3/libexec/src/testing/benchmark.go:250 +0x70
exit status 2
FAIL	github.com/patrobinson/replicate-boltdb-bug	1.013s

Code to replicate

main.go

package main

import (
	"github.com/boltdb/bolt"
	"time"
)

var db *bolt.DB

func main() {
	setUp()
	for i := 0; i < 100000; i++ {
		run()
	}
}

func setUp() {
	var err error
	db, err = bolt.Open("foo", 0600, &bolt.Options{Timeout: 1 * time.Second})
	db.Update(func(tx *bolt.Tx) error {
		_, err = tx.CreateBucket([]byte("bar"))
		if err != nil {
			return err
		}
		return nil
	})
}

func run() {
	db.Update(func(tx *bolt.Tx) error {
			b := tx.Bucket([]byte("bar"))
			err := b.Put([]byte("foo"), []byte("bar"))
			return err
	})
}

main_test.go

package main

import "testing"

func BenchmarkRun(b *testing.B) {
	setUp()
	for i := 0; i < b.N; i++ {
		run()
	}
}

Running the program itself doesn't trigger the crash, but go test -bench . does.

bolt.Open returns an error because the db is still open after the first BenchmarkRun call.

I have a lot of questions about why BenchmarkRun is opening the DB more than ocne but that doesn't seem like it's relevant to this issue. Thank you.