From 6379ae6c7f861e884bb21bcf01ae4d1b597d72ab Mon Sep 17 00:00:00 2001 From: John Sully Date: Thu, 21 Jan 2021 17:18:54 +0000 Subject: [PATCH] Fix races in free Former-commit-id: 3881d5c1f22f022855c0abcf7b0c2070e204c0a3 --- src/dict.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/dict.cpp b/src/dict.cpp index e0b193312..966abc255 100644 --- a/src/dict.cpp +++ b/src/dict.cpp @@ -277,6 +277,7 @@ void dictRehashAsync(dictAsyncRehashCtl *ctl) { void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl) { dict *d = ctl->dict; + d->asyncdata = nullptr; // dictFreeUnlinkedEntry won't actually free if we don't NULL this // Was the dictionary free'd while we were in flight? if (ctl->release) { @@ -315,9 +316,9 @@ void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl) { // Note: We may not find it if the entry was just unlinked but reused elsewhere } } + assert(ctl->deGCList == nullptr); delete ctl; - d->asyncdata = nullptr; } long long timeInMilliseconds(void) { @@ -475,7 +476,7 @@ static dictEntry *dictGenericDelete(dict *d, const void *key, int nofree) { else d->ht[table].table[idx] = he->next; if (!nofree) { - if (d->asyncdata != nullptr) { + if (table == 0 && d->asyncdata != nullptr) { he->next = d->asyncdata->deGCList; d->asyncdata->deGCList = he->next; } else { @@ -530,9 +531,14 @@ dictEntry *dictUnlink(dict *ht, const void *key) { * to dictUnlink(). It's safe to call this function with 'he' = NULL. */ void dictFreeUnlinkedEntry(dict *d, dictEntry *he) { if (he == NULL) return; - dictFreeKey(d, he); - dictFreeVal(d, he); - zfree(he); + if (d->asyncdata) { + he->next = d->asyncdata->deGCList; + d->asyncdata->deGCList = he; + } else { + dictFreeKey(d, he); + dictFreeVal(d, he); + zfree(he); + } } /* Destroy an entire dictionary */ @@ -548,9 +554,14 @@ int _dictClear(dict *d, dictht *ht, void(callback)(void *)) { if ((he = ht->table[i]) == NULL) continue; while(he) { nextHe = he->next; - dictFreeKey(d, he); - dictFreeVal(d, he); - zfree(he); + if (i == 0 && d->asyncdata) { + he->next = d->asyncdata->deGCList; + d->asyncdata->deGCList = he; + } else { + dictFreeKey(d, he); + dictFreeVal(d, he); + zfree(he); + } ht->used--; he = nextHe; }