leveldb: fix panic on close when there is inflight Get (#149)
diff --git a/leveldb/db.go b/leveldb/db.go
index eb6abd0..1aed209 100644
--- a/leveldb/db.go
+++ b/leveldb/db.go
@@ -1062,6 +1062,8 @@
if db.journal != nil {
db.journal.Close()
db.journalWriter.Close()
+ db.journal = nil
+ db.journalWriter = nil
}
if db.writeDelayN > 0 {
@@ -1077,15 +1079,11 @@
if err1 := db.closer.Close(); err == nil {
err = err1
}
+ db.closer = nil
}
- // NIL'ing pointers.
- db.s = nil
- db.mem = nil
- db.frozenMem = nil
- db.journal = nil
- db.journalWriter = nil
- db.closer = nil
+ // Clear memdbs.
+ db.clearMems()
return err
}
diff --git a/leveldb/db_state.go b/leveldb/db_state.go
index facf64f..590b24f 100644
--- a/leveldb/db_state.go
+++ b/leveldb/db_state.go
@@ -153,7 +153,7 @@
func (db *DB) getMems() (e, f *memDB) {
db.memMu.RLock()
defer db.memMu.RUnlock()
- if db.mem == nil {
+ if db.mem == nil && !db.isClosed() {
panic("nil effective mem")
}
db.mem.incref()
@@ -167,7 +167,7 @@
func (db *DB) getEffectiveMem() *memDB {
db.memMu.RLock()
defer db.memMu.RUnlock()
- if db.mem == nil {
+ if db.mem == nil && !db.isClosed() {
panic("nil effective mem")
}
db.mem.incref()
@@ -205,6 +205,14 @@
db.memMu.Unlock()
}
+// Clear mems ptr; used by DB.Close().
+func (db *DB) clearMems() {
+ db.memMu.Lock()
+ db.mem = nil
+ db.frozenMem = nil
+ db.memMu.Unlock()
+}
+
// Set closed flag; return true if not already closed.
func (db *DB) setClosed() bool {
return atomic.CompareAndSwapUint32(&db.closed, 0, 1)
diff --git a/leveldb/db_write.go b/leveldb/db_write.go
index 5576761..37acb3f 100644
--- a/leveldb/db_write.go
+++ b/leveldb/db_write.go
@@ -73,6 +73,10 @@
v := db.s.version()
defer v.release()
mdb = db.getEffectiveMem()
+ if mdb == nil {
+ err = ErrClosed
+ return false
+ }
defer func() {
if retry {
mdb.decref()
@@ -310,6 +314,9 @@
// Check for overlaps in memdb.
mdb := db.getEffectiveMem()
+ if mdb == nil {
+ return ErrClosed
+ }
defer mdb.decref()
if isMemOverlaps(db.s.icmp, mdb.DB, r.Start, r.Limit) {
// Memdb compaction.
diff --git a/leveldb/session.go b/leveldb/session.go
index b0d3fef..3a1e6d2 100644
--- a/leveldb/session.go
+++ b/leveldb/session.go
@@ -87,7 +87,7 @@
}
s.manifest = nil
s.manifestWriter = nil
- s.stVersion = nil
+ s.setVersion(&version{})
}
// Release session lock.