Skip to content

Commit

Permalink
MB-43028: [1/2] Make overhead tracking safe at VBucket destruction
Browse files Browse the repository at this point in the history
Merging http://review.couchbase.org/c/kv_engine/+/136495 into master
uncovered santizer issues (mad-hatter CV runs an older Clang and did
not identify these issues).

This patch resolves one of these issues, before the above patch may
be merged to master.

WARNING: ThreadSanitizer: heap-use-after-free (pid=73551)
   Read of size 8 at 0x7b5800000310 by main thread:
     #0 operator() ../kv_engine/engines/ep/src/ephemeral_bucket.cc:301 (libep.so+0x00000034705f)
     #1 std::_Function_handler<void (long), EphemeralBucket::makeVBucket(...>::_M_invoke(std::_Any_data const&, long&&)
     #3 ~Checkpoint ../kv_engine/engines/ep/src/checkpoint.cc:228 (libep.so+0x00000019dc97)

     #10 ~CheckpointManager ../kv_engine/engines/ep/src/checkpoint_manager.h:73 (libep.so+0x00000042f782)
     ...
     #13 ~VBucket ../kv_engine/engines/ep/src/vbucket.cc:286 (libep.so+0x00000041689a)

During VBucket destruction, the CheckpointManager member, and any
remaining Checkpoints it holds are destroyed. This can trigger the
memOverheadChangedCallback, as destroying Checkpoints reduces the
memory overhead.

This was unsafe, as the state member had already been destroyed as it
is declared later in VBucket.

Move the CheckpointManager to be declared after state, so it is
destroyed first.

Change-Id: I0a34d3a11cd053f18f3168d6fbbb9dc974bbd2fc
Reviewed-on: http://review.couchbase.org/c/kv_engine/+/141492
Reviewed-by: Dave Rigby <[email protected]>
Tested-by: Build Bot <[email protected]>
Well-Formed: Build Bot <[email protected]>
  • Loading branch information
jameseh96 authored and daverigby committed Dec 4, 2020
1 parent ac69da7 commit 6badce2
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 11 deletions.
16 changes: 8 additions & 8 deletions engines/ep/src/vbucket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,6 @@ VBucket::VBucket(Vbid i,
const nlohmann::json& replTopology,
uint64_t maxVisibleSeqno)
: ht(st, std::move(valFact), config.getHtSize(), config.getHtLocks()),
checkpointManager(std::make_unique<CheckpointManager>(st,
i,
chkConfig,
lastSeqno,
lastSnapStart,
lastSnapEnd,
maxVisibleSeqno,
flusherCb)),
failovers(std::move(table)),
opsCreate(0),
opsDelete(0),
Expand All @@ -216,6 +208,14 @@ VBucket::VBucket(Vbid i,
id(i),
state(newState),
initialState(initState),
checkpointManager(std::make_unique<CheckpointManager>(st,
i,
chkConfig,
lastSeqno,
lastSnapStart,
lastSnapEnd,
maxVisibleSeqno,
flusherCb)),
purge_seqno(purgeSeqno),
takeover_backed_up(false),
persistedRange(lastSnapStart, lastSnapEnd),
Expand Down
12 changes: 9 additions & 3 deletions engines/ep/src/vbucket.h
Original file line number Diff line number Diff line change
Expand Up @@ -907,9 +907,6 @@ class VBucket : public std::enable_shared_from_this<VBucket> {

HashTable ht;

/// Manager of this vBucket's checkpoints. unique_ptr for pimpl.
std::unique_ptr<CheckpointManager> checkpointManager;

/**
* Searches for a 'valid' StoredValue in the VBucket.
*
Expand Down Expand Up @@ -2471,6 +2468,15 @@ class VBucket : public std::enable_shared_from_this<VBucket> {

vbucket_state_t initialState;

public:
/**
* Manager of this vBucket's checkpoints. unique_ptr for pimpl.
* Declared after state as Checkpoint destruction may update stats
* based on the vbucket's current state.
*/
std::unique_ptr<CheckpointManager> checkpointManager;

private:
/**
* The replication topology, set as part of SET_VBUCKET_STATE.
* It is encoded as nlohmann::json array of (max 2) replication chains.
Expand Down

0 comments on commit 6badce2

Please sign in to comment.