Skip to content

Commit

Permalink
Merge "Fix memory leaks when stoppping memcached" from Tomasz
Browse files Browse the repository at this point in the history
"
Fixes ASAN complaints in debug mode when memcached is stopped.

All leaks are created during initialization, so should not affect normal
operation.
"

* tag 'fix-mem-leaks-memcached' of github.com:tgrabiec/seastar:
  memcached: Avoid leaking of slab_allocator
  core/slab: Destroy slab classes before destroying slab pages
  memcached: Avoid leaking the buckets array when cache is destroyed
  • Loading branch information
avikivity committed Sep 25, 2018
2 parents 9d1f929 + f97700a commit 873f95f
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 8 deletions.
17 changes: 9 additions & 8 deletions apps/memcached/memcache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static constexpr double default_slab_growth_factor = 1.25;
static constexpr uint64_t default_slab_page_size = 1UL*MB;
static constexpr uint64_t default_per_cpu_slab_size = 0UL; // zero means reclaimer is enabled.
static __thread slab_allocator<item>* slab;
static thread_local std::unique_ptr<slab_allocator<item>> slab_holder;

template<typename T>
using optional = boost::optional<T>;
Expand Down Expand Up @@ -370,7 +371,7 @@ class cache {
static constexpr size_t initial_bucket_count = 1 << 10;
static constexpr float load_factor = 0.75f;
size_t _resize_up_threshold = load_factor * initial_bucket_count;
cache_type::bucket_type* _buckets;
std::vector<cache_type::bucket_type> _buckets;
cache_type _cache;
seastar::timer_set<item, &item::_timer_link> _alive;
timer<clock_type> _timer;
Expand Down Expand Up @@ -490,22 +491,21 @@ class cache {
void maybe_rehash() {
if (_cache.size() >= _resize_up_threshold) {
auto new_size = _cache.bucket_count() * 2;
auto old_buckets = _buckets;
std::vector<cache_type::bucket_type> old_buckets;
try {
_buckets = new cache_type::bucket_type[new_size];
old_buckets = std::exchange(_buckets, std::vector<cache_type::bucket_type>(new_size));
} catch (const std::bad_alloc& e) {
_stats._resize_failure++;
return;
}
_cache.rehash(typename cache_type::bucket_traits(_buckets, new_size));
delete[] old_buckets;
_cache.rehash(typename cache_type::bucket_traits(_buckets.data(), new_size));
_resize_up_threshold = _cache.bucket_count() * load_factor;
}
}
public:
cache(uint64_t per_cpu_slab_size, uint64_t slab_page_size)
: _buckets(new cache_type::bucket_type[initial_bucket_count])
, _cache(cache_type::bucket_traits(_buckets, initial_bucket_count))
: _buckets(initial_bucket_count)
, _cache(cache_type::bucket_traits(_buckets.data(), initial_bucket_count))
{
using namespace std::chrono;

Expand All @@ -516,8 +516,9 @@ class cache {
_flush_timer.set_callback([this] { flush_all(); });

// initialize per-thread slab allocator.
slab = new slab_allocator<item>(default_slab_growth_factor, per_cpu_slab_size, slab_page_size,
slab_holder = std::make_unique<slab_allocator<item>>(default_slab_growth_factor, per_cpu_slab_size, slab_page_size,
[this](item& item_ref) { erase<true, true, false>(item_ref); _stats._evicted++; });
slab = slab_holder.get();
#ifdef __DEBUG__
static bool print_slab_classes = true;
if (print_slab_classes) {
Expand Down
1 change: 1 addition & 0 deletions core/slab.hh
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ public:

~slab_allocator()
{
_slab_classes.clear();
_slab_page_desc_lru.clear();
for (auto desc : _slab_pages_vector) {
if (!desc) {
Expand Down

0 comments on commit 873f95f

Please sign in to comment.