diff --git a/src/dict.c b/src/dict.c index 32249028320db66e9fb245e6cfe829987983f65d..5e327a79438b425364b0117fd6d1d83f0261af19 100644 --- a/src/dict.c +++ b/src/dict.c @@ -478,8 +478,9 @@ dictEntry *dictUnlink(dict *ht, const void *key) { } /* You need to call this function to really free the entry after a call - * to dictUnlink(). */ + * 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); diff --git a/src/lazyfree.c b/src/lazyfree.c index dba3f00e256d4dbfe33c0a554df4af5f70e3b3e1..c05252159ae5590033e3b7fe712b90640ed140eb 100644 --- a/src/lazyfree.c +++ b/src/lazyfree.c @@ -57,7 +57,7 @@ int dbAsyncDelete(redisDb *db, robj *key) { /* If the value is composed of a few allocations, to free in a lazy way * is actually just slower... So under a certain limit we just free * the object synchronously. */ - dictEntry *de = dictFind(db->dict,key->ptr); + dictEntry *de = dictUnlink(db->dict,key->ptr); if (de) { robj *val = dictGetVal(de); size_t free_effort = lazyfreeGetFreeEffort(val); @@ -73,7 +73,8 @@ int dbAsyncDelete(redisDb *db, robj *key) { /* Release the key-val pair, or just the key if we set the val * field to NULL in order to lazy free it later. */ - if (dictDelete(db->dict,key->ptr) == DICT_OK) { + if (de) { + dictFreeUnlinkedEntry(db->dict,de); if (server.cluster_enabled) slotToKeyDel(key); return 1; } else { diff --git a/src/t_zset.c b/src/t_zset.c index 81e6e57c53bfc38171b66aa69457d217e45c42ad..8d905be02596d4868491f172073493d0bdc5bc1d 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -1387,7 +1387,7 @@ int zsetDel(robj *zobj, sds ele) { dictEntry *de; double score; - de = dictFind(zs->dict,ele); + de = dictUnlink(zs->dict,ele); if (de != NULL) { /* Get the score in order to delete from the skiplist later. */ score = *(double*)dictGetVal(de); @@ -1397,12 +1397,11 @@ int zsetDel(robj *zobj, sds ele) { * actually releases the SDS string representing the element, * which is shared between the skiplist and the hash table, so * we need to delete from the skiplist as the final step. */ - int retval1 = dictDelete(zs->dict,ele); + dictFreeUnlinkedEntry(zs->dict,de); /* Delete from skiplist. */ - int retval2 = zslDelete(zs->zsl,score,ele,NULL); - - serverAssert(retval1 == DICT_OK && retval2); + int retval = zslDelete(zs->zsl,score,ele,NULL); + serverAssert(retval); if (htNeedsResize(zs->dict)) dictResize(zs->dict); return 1;