diff --git a/db/db_range_del_test.cc b/db/db_range_del_test.cc index 8b7bba7cf..918fadbaf 100644 --- a/db/db_range_del_test.cc +++ b/db/db_range_del_test.cc @@ -660,6 +660,16 @@ TEST_F(DBRangeDelTest, TableEvictedDuringScan) { ASSERT_EQ(kNum, expected); delete iter; db_->ReleaseSnapshot(snapshot); + + // Also test proper cache handling in GetRangeTombstoneIterator, + // via TablesRangeTombstoneSummary. (This once triggered memory leak + // report with ASAN.) + opts.max_open_files = 1; + Reopen(opts); + + std::string str; + ASSERT_OK(dbfull()->TablesRangeTombstoneSummary(db_->DefaultColumnFamily(), + 100, &str)); } TEST_F(DBRangeDelTest, GetCoveredKeyFromMutableMemtable) { diff --git a/db/table_cache.cc b/db/table_cache.cc index 2e4d2a58a..a80f69223 100644 --- a/db/table_cache.cc +++ b/db/table_cache.cc @@ -297,6 +297,7 @@ Status TableCache::GetRangeTombstoneIterator( const InternalKeyComparator& internal_comparator, const FileMetaData& file_meta, std::unique_ptr* out_iter) { + assert(out_iter); const FileDescriptor& fd = file_meta.fd; Status s; TableReader* t = fd.table_reader; @@ -308,8 +309,15 @@ Status TableCache::GetRangeTombstoneIterator( } } if (s.ok()) { + // Note: NewRangeTombstoneIterator could return nullptr out_iter->reset(t->NewRangeTombstoneIterator(options)); - assert(out_iter); + } + if (handle) { + if (*out_iter) { + (*out_iter)->RegisterCleanup(&UnrefEntry, cache_, handle); + } else { + ReleaseHandle(handle); + } } return s; }