Skip to content
This repository has been archived by the owner on Mar 9, 2019. It is now read-only.

page already freed on certain builds #749

Open
tehsphinx opened this issue Mar 26, 2018 · 0 comments
Open

page already freed on certain builds #749

tehsphinx opened this issue Mar 26, 2018 · 0 comments

Comments

@tehsphinx
Copy link

tehsphinx commented Mar 26, 2018

Sorry to bring up another issue with this headline... I already checked the other two issues and do not have the impression that they match my case.

Here my error

panic: page 4 already freed

goroutine 416 [running]:
.../vendor/github.com/boltdb/bolt.(*freelist).free(0x202f7ec0, 0x5, 0x0, 0x3014000)
/ext-go/1/src/.../vendor/github.com/boltdb/bolt/freelist.go:121 +0x263
.../vendor/github.com/boltdb/bolt.(*node).spill(0x20356d40, 0x2064bc64, 0x6)
/ext-go/1/src/.../vendor/github.com/boltdb/bolt/node.go:363 +0x19f
.../vendor/github.com/boltdb/bolt.(*Bucket).spill(0x2032eb0c, 0xe, 0x38554104)
/ext-go/1/src/.../vendor/github.com/boltdb/bolt/bucket.go:570 +0x13d
.../vendor/github.com/boltdb/bolt.(*Tx).Commit(0x2032eb00, 0x0, 0x0)
/ext-go/1/src/.../vendor/github.com/boltdb/bolt/tx.go:163 +0xff
.../vendor/github.com/boltdb/bolt.(*DB).Update(0x20244fc0, 0x2056de80, 0x0, 0x0)
/ext-go/1/src/.../vendor/github.com/boltdb/bolt/db.go:605 +0xc9

Here my Code snippet:

// Add adds a value to the db using NextSequence to autoincrement the key
func (s *DB) Add(tableName string, value []byte) (uint64, error) {
	var id uint64
	err := s.Conn.Update(func(tx *bolt.Tx) error {
		bt, err := tx.CreateBucketIfNotExists([]byte(tableName))
		if err != nil {
			return err
		}

		id, err = bt.NextSequence()
		if err != nil {
			return err
		}

		return bt.Put(itob(id), value)
	})
	return id, errors.WithStack(err)
}

// itob returns an 8-byte big endian representation of v.
func itob(i uint64) []byte {
	b := make([]byte, 8)
	binary.BigEndian.PutUint64(b, i)
	return b
}

The error occurs the second time this code is executed (every time).

The code runs fine on MacOS (amd64) and Windows (386) without cgo. Disabling cgo disables a few packages that use windows dlls.
When compiling the final version with cgo (and dlls) using xgo --targets=windows/386 . the resulting windows executable will show the above issue.

I added some logs to the boltdb code and checked which pages are being freed. On every call the same pages are being freed. The node.pgid on node.go:363 is also the same on every call (calls are several secods apart). Why?

Since in one of the other issues on this topic there is talk about race conditions I made sure the entire connection is used by a single goroutine using the action pattern. This did not resolve the issue either:

// Add adds a value to the db using NextSequence to autoincrement the key
func (s *DB) Add(tableName string, value []byte) (uint64, error) {
	// added this to make sure there is no other goroutine using the byte array at the same time
	var valCopy = make([]byte, 0, len(value))
	valCopy = append(valCopy, value...)

	var id uint64
	chErr := make(chan error)
	s.Run(s.Action)
	s.Action <- func() {
		err := s.Conn.Update(func(tx *bolt.Tx) error {
			bt, err := tx.CreateBucketIfNotExists([]byte(tableName))
			if err != nil {
				return err
			}

			id, err = bt.NextSequence()
			if err != nil {
				return err
			}

			return bt.Put(itob(id), valCopy)
		})
		chErr <- err
	}
	err := <-chErr
	return id, errors.WithStack(err)
}

Anyone any idea on how to solve this issue?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant