Fix races in free
Former-commit-id: 3881d5c1f22f022855c0abcf7b0c2070e204c0a3
This commit is contained in:
parent
c6c1084dd8
commit
5d161ca2f2
27
src/dict.cpp
27
src/dict.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user