From 8766e81079dd4e26b0f5e1b04b8fc319b8d13eb7 Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 24 Jan 2013 11:27:10 +0100 Subject: [PATCH] Fix decrRefCount() prototype from void to robj pointer. decrRefCount used to get its argument as a void* pointer in order to be used as destructor where a 'void free_object(void*)' prototype is expected. However this made simpler to introduce bugs by freeing the wrong pointer. This commit fixes the argument type and introduces a new wrapper called decrRefCountVoid() that can be used when the void* argument is needed. --- src/aof.c | 2 +- src/networking.c | 6 +++--- src/object.c | 11 ++++++++--- src/redis.h | 3 ++- src/t_list.c | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/aof.c b/src/aof.c index 8dc1dd188..2265222cc 100644 --- a/src/aof.c +++ b/src/aof.c @@ -456,7 +456,7 @@ struct redisClient *createFakeClient(void) { c->reply_bytes = 0; c->obuf_soft_limit_reached_time = 0; c->watched_keys = listCreate(); - listSetFreeMethod(c->reply,decrRefCount); + listSetFreeMethod(c->reply,decrRefCountVoid); listSetDupMethod(c->reply,dupClientReplyValue); initClientMultiState(c); return c; diff --git a/src/networking.c b/src/networking.c index 6e5d32489..0853ad923 100644 --- a/src/networking.c +++ b/src/networking.c @@ -89,17 +89,17 @@ redisClient *createClient(int fd) { c->reply = listCreate(); c->reply_bytes = 0; c->obuf_soft_limit_reached_time = 0; - listSetFreeMethod(c->reply,decrRefCount); + listSetFreeMethod(c->reply,decrRefCountVoid); listSetDupMethod(c->reply,dupClientReplyValue); c->bpop.keys = dictCreate(&setDictType,NULL); c->bpop.timeout = 0; c->bpop.target = NULL; c->io_keys = listCreate(); c->watched_keys = listCreate(); - listSetFreeMethod(c->io_keys,decrRefCount); + listSetFreeMethod(c->io_keys,decrRefCountVoid); c->pubsub_channels = dictCreate(&setDictType,NULL); c->pubsub_patterns = listCreate(); - listSetFreeMethod(c->pubsub_patterns,decrRefCount); + listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid); listSetMatchMethod(c->pubsub_patterns,listMatchObjects); if (fd != -1) listAddNodeTail(server.clients,c); initClientMultiState(c); diff --git a/src/object.c b/src/object.c index 00cf023b0..bb5f6729d 100644 --- a/src/object.c +++ b/src/object.c @@ -215,9 +215,7 @@ void incrRefCount(robj *o) { o->refcount++; } -void decrRefCount(void *obj) { - robj *o = obj; - +void decrRefCount(robj *o) { if (o->refcount <= 0) redisPanic("decrRefCount against refcount <= 0"); if (o->refcount == 1) { switch(o->type) { @@ -234,6 +232,13 @@ void decrRefCount(void *obj) { } } +/* This variant of decrRefCount() gets its argument as void, and is useful + * as free method in data structures that expect a 'void free_object(void*)' + * prototype for the free method. */ +void decrRefCountVoid(void *o) { + decrRefCount(o); +} + /* This function set the ref count to zero without freeing the object. * It is useful in order to pass a new object to functions incrementing * the ref count of the received object. Example: diff --git a/src/redis.h b/src/redis.h index eb70516db..97d49d511 100644 --- a/src/redis.h +++ b/src/redis.h @@ -989,7 +989,8 @@ void discardTransaction(redisClient *c); void flagTransaction(redisClient *c); /* Redis object implementation */ -void decrRefCount(void *o); +void decrRefCount(robj *o); +void decrRefCountVoid(void *o); void incrRefCount(robj *o); robj *resetRefCount(robj *obj); void freeStringObject(robj *o); diff --git a/src/t_list.c b/src/t_list.c index 16b5e1be5..d3d3f6c69 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -275,7 +275,7 @@ void listTypeConvert(robj *subject, int enc) { if (enc == REDIS_ENCODING_LINKEDLIST) { list *l = listCreate(); - listSetFreeMethod(l,decrRefCount); + listSetFreeMethod(l,decrRefCountVoid); /* listTypeGet returns a robj with incremented refcount */ li = listTypeInitIterator(subject,0,REDIS_TAIL); -- GitLab