aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2014-06-13 12:07:37 -0600
committerBen Johnson <benbjohnson@yahoo.com>2014-06-13 12:07:37 -0600
commitdefdb743cdca840890fea24c3111a7bffe5cc0a3 (patch)
tree08e770860311a77754e49bbf68a240b58f5c9c2c
parentMerge pull request #191 from benbjohnson/win-ftw (diff)
downloaddedo-defdb743cdca840890fea24c3111a7bffe5cc0a3.tar.gz
dedo-defdb743cdca840890fea24c3111a7bffe5cc0a3.tar.xz
Fix deadlock on remmap.
This commit fixes a deadlock situation that can occur when Bolt's database size crosses a threshold and requires remapping the mmap.
-rw-r--r--db.go14
1 files changed, 9 insertions, 5 deletions
diff --git a/db.go b/db.go
index 8f80515..0b4631f 100644
--- a/db.go
+++ b/db.go
@@ -340,17 +340,20 @@ func (db *DB) Begin(writable bool) (*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 write lock so all transactions must finish before it can be
// remapped.
db.mmaplock.RLock()
- // Lock the meta pages while we initialize the transaction.
- db.metalock.Lock()
-
// Exit if the database is not open yet.
if !db.opened {
db.mmaplock.RUnlock()
+ db.metalock.Unlock()
return nil, ErrDatabaseNotOpen
}
@@ -411,11 +414,12 @@ func (db *DB) beginRWTx() (*Tx, error) {
// removeTx removes a transaction from the database.
func (db *DB) removeTx(tx *Tx) {
- db.metalock.Lock()
-
// Release the read lock on the mmap.
db.mmaplock.RUnlock()
+ // Use the meta lock to restrict access to the DB object.
+ db.metalock.Lock()
+
// Remove the transaction.
for i, t := range db.txs {
if t == tx {