Fix races in free

Former-commit-id: 3881d5c1f22f022855c0abcf7b0c2070e204c0a3
This commit is contained in:
John Sully 2021-01-21 17:18:54 +00:00
parent c6c1084dd8
commit 5d161ca2f2

View File

@ -277,6 +277,7 @@ void dictRehashAsync(dictAsyncRehashCtl *ctl) {
void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl) { void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl) {
dict *d = ctl->dict; 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? // Was the dictionary free'd while we were in flight?
if (ctl->release) { 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 // Note: We may not find it if the entry was just unlinked but reused elsewhere
} }
} }
assert(ctl->deGCList == nullptr);
delete ctl; delete ctl;
d->asyncdata = nullptr;
} }
long long timeInMilliseconds(void) { long long timeInMilliseconds(void) {
@ -475,7 +476,7 @@ static dictEntry *dictGenericDelete(dict *d, const void *key, int nofree) {
else else
d->ht[table].table[idx] = he->next; d->ht[table].table[idx] = he->next;
if (!nofree) { if (!nofree) {
if (d->asyncdata != nullptr) { if (table == 0 && d->asyncdata != nullptr) {
he->next = d->asyncdata->deGCList; he->next = d->asyncdata->deGCList;
d->asyncdata->deGCList = he->next; d->asyncdata->deGCList = he->next;
} else { } else {
@ -530,9 +531,14 @@ dictEntry *dictUnlink(dict *ht, const void *key) {
* to dictUnlink(). It's safe to call this function with 'he' = NULL. */ * to dictUnlink(). It's safe to call this function with 'he' = NULL. */
void dictFreeUnlinkedEntry(dict *d, dictEntry *he) { void dictFreeUnlinkedEntry(dict *d, dictEntry *he) {
if (he == NULL) return; if (he == NULL) return;
dictFreeKey(d, he); if (d->asyncdata) {
dictFreeVal(d, he); he->next = d->asyncdata->deGCList;
zfree(he); d->asyncdata->deGCList = he;
} else {
dictFreeKey(d, he);
dictFreeVal(d, he);
zfree(he);
}
} }
/* Destroy an entire dictionary */ /* Destroy an entire dictionary */
@ -548,9 +554,14 @@ int _dictClear(dict *d, dictht *ht, void(callback)(void *)) {
if ((he = ht->table[i]) == NULL) continue; if ((he = ht->table[i]) == NULL) continue;
while(he) { while(he) {
nextHe = he->next; nextHe = he->next;
dictFreeKey(d, he); if (i == 0 && d->asyncdata) {
dictFreeVal(d, he); he->next = d->asyncdata->deGCList;
zfree(he); d->asyncdata->deGCList = he;
} else {
dictFreeKey(d, he);
dictFreeVal(d, he);
zfree(he);
}
ht->used--; ht->used--;
he = nextHe; he = nextHe;
} }