diff --git a/db.go b/db.go index 8a1021308..f0608d993 100644 --- a/db.go +++ b/db.go @@ -625,6 +625,9 @@ func (db *DB) close() (err error) { db.threshold.close() if db.opt.InMemory { + for _, mem := range db.imm{ + mem.DecrRef() + } return } diff --git a/issue_2205_test.go b/issue_2205_test.go new file mode 100644 index 000000000..a893768cb --- /dev/null +++ b/issue_2205_test.go @@ -0,0 +1,34 @@ +package badger + +import ( + "testing" +) + +func TestIssue2205_MemoryLeak(t *testing.T) { + // Loop 1000 times to force the leak to accumulate + for i := 0; i < 1000; i++ { + // Initialize an in-memory database configuration + opt := DefaultOptions("").WithInMemory(true) + opt.Logger = nil // Turn off logging so our terminal doesn't get spammed + + db, err := Open(opt) + if err != nil { + t.Fatalf("Failed to open DB on iteration %d: %v", i, err) + } + + // Perform a single write transaction + err = db.Update(func(txn *Txn) error { + return txn.Set([]byte("leak-test"), []byte("value")) + }) + if err != nil { + t.Fatalf("Failed to write on iteration %d: %v", i, err) + } + + // Close the database. This is where the bug lives! + // It is supposed to clean up everything, but it's leaving something behind. + err = db.Close() + if err != nil { + t.Fatalf("Failed to close DB on iteration %d: %v", i, err) + } + } +} \ No newline at end of file