Merge pull request #194 from benbjohnson/fix-deadlock

Fix deadlock on remmap.
master
Ben Johnson 2014-06-13 12:29:59 -06:00
commit 8137a18374
1 changed files with 9 additions and 5 deletions

14
db.go
View File

@ -340,17 +340,20 @@ func (db *DB) Begin(writable bool) (*Tx, error) {
} }
func (db *DB) beginTx() (*Tx, error) { func (db *DB) beginTx() (*Tx, error) {
// Lock the meta pages while we initialize the transaction. We obtain
// the meta lock before the mmap lock because that's the order that the
// write transaction will obtain them.
db.metalock.Lock()
// Obtain a read-only lock on the mmap. When the mmap is remapped it will // Obtain a read-only lock on the mmap. When the mmap is remapped it will
// obtain a write lock so all transactions must finish before it can be // obtain a write lock so all transactions must finish before it can be
// remapped. // remapped.
db.mmaplock.RLock() db.mmaplock.RLock()
// Lock the meta pages while we initialize the transaction.
db.metalock.Lock()
// Exit if the database is not open yet. // Exit if the database is not open yet.
if !db.opened { if !db.opened {
db.mmaplock.RUnlock() db.mmaplock.RUnlock()
db.metalock.Unlock()
return nil, ErrDatabaseNotOpen return nil, ErrDatabaseNotOpen
} }
@ -411,11 +414,12 @@ func (db *DB) beginRWTx() (*Tx, error) {
// removeTx removes a transaction from the database. // removeTx removes a transaction from the database.
func (db *DB) removeTx(tx *Tx) { func (db *DB) removeTx(tx *Tx) {
db.metalock.Lock()
// Release the read lock on the mmap. // Release the read lock on the mmap.
db.mmaplock.RUnlock() db.mmaplock.RUnlock()
// Use the meta lock to restrict access to the DB object.
db.metalock.Lock()
// Remove the transaction. // Remove the transaction.
for i, t := range db.txs { for i, t := range db.txs {
if t == tx { if t == tx {