Fix reference counting failure in the dict. This is caused by std::swap also swapping refcounts

This commit is contained in:
John Sully 2022-05-16 22:34:50 +00:00
parent 242d6aabb2
commit 51d3e2cbbc
3 changed files with 36 additions and 13 deletions

View File

@ -204,7 +204,7 @@ int dictMerge(dict *dst, dict *src)
if (dictSize(dst) == 0)
{
std::swap(*dst, *src);
dict::swap(*dst, *src);
std::swap(dst->pauserehash, src->pauserehash);
return DICT_OK;
}
@ -212,7 +212,7 @@ int dictMerge(dict *dst, dict *src)
size_t expectedSize = dictSize(src) + dictSize(dst);
if (dictSize(src) > dictSize(dst) && src->asyncdata == nullptr && dst->asyncdata == nullptr)
{
std::swap(*dst, *src);
dict::swap(*dst, *src);
std::swap(dst->pauserehash, src->pauserehash);
}
@ -465,6 +465,18 @@ bool dictRehashSomeAsync(dictAsyncRehashCtl *ctl, size_t hashes) {
return ctl->hashIdx < ctl->queue.size();
}
void discontinueAsyncRehash(dict *d) {
if (d->asyncdata != nullptr) {
auto adata = d->asyncdata;
while (adata != nullptr) {
adata->abondon = true;
adata = adata->next;
}
d->rehashidx = 0;
}
}
void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl, bool fFree) {
dict *d = ctl->dict;
assert(ctl->done);

View File

@ -110,12 +110,16 @@ struct dictAsyncRehashCtl {
std::atomic<bool> abondon { false };
dictAsyncRehashCtl(struct dict *d, dictAsyncRehashCtl *next);
dictAsyncRehashCtl(const dictAsyncRehashCtl&) = delete;
dictAsyncRehashCtl(dictAsyncRehashCtl&&) = delete;
~dictAsyncRehashCtl();
};
#else
struct dictAsyncRehashCtl;
#endif
void discontinueAsyncRehash(dict *d);
typedef struct dict {
dictType *type;
void *privdata;
@ -125,6 +129,24 @@ typedef struct dict {
dictAsyncRehashCtl *asyncdata;
int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */
uint8_t noshrink = false;
#ifdef __cplusplus
dict() = default;
dict(dict &) = delete; // No Copy Ctor
static void swap(dict& a, dict& b) {
discontinueAsyncRehash(&a);
discontinueAsyncRehash(&b);
std::swap(a.type, b.type);
std::swap(a.privdata, b.privdata);
std::swap(a.ht[0], b.ht[0]);
std::swap(a.ht[1], b.ht[1]);
std::swap(a.rehashidx, b.rehashidx);
// Never swap refcount - they are attached to the specific dict obj
std::swap(a.pauserehash, b.pauserehash);
std::swap(a.noshrink, b.noshrink);
}
#endif
} dict;
/* If safe is set to 1 this is a safe iterator, that means, you can call

View File

@ -26,17 +26,6 @@ public:
std::vector<dictEntry*> vecde;
};
void discontinueAsyncRehash(dict *d) {
if (d->asyncdata != nullptr) {
auto adata = d->asyncdata;
while (adata != nullptr) {
adata->abondon = true;
adata = adata->next;
}
d->rehashidx = 0;
}
}
const redisDbPersistentDataSnapshot *redisDbPersistentData::createSnapshot(uint64_t mvccCheckpoint, bool fOptional)
{
serverAssert(GlobalLocksAcquired());