summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-09-05 15:14:36 +0200
committerantirez <antirez@gmail.com>2014-09-05 15:14:36 +0200
commitc86e10df4bc28b680f84d57df1e733523db5c2b3 (patch)
treeaed12296b0c0886c37d8061ec64c1063b1217acb
parent7c3aeb16e9a99c43636f6edecb1c904a638d6581 (diff)
downloadredis-c86e10df4bc28b680f84d57df1e733523db5c2b3.tar.gz
Correct cleanup when aborting AOF loading.
Because of the new ability to start with a truncated AOF, we need to correctly release all the memory on EOF error. Otherwise there is a small leak, that is not really a problem, but causes a false positive in the tests that detect memory leaks.
-rw-r--r--src/aof.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/src/aof.c b/src/aof.c
index 2698650d6..3bc598f02 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -577,6 +577,14 @@ struct redisClient *createFakeClient(void) {
return c;
}
+void freeFakeClientArgv(struct redisClient *c) {
+ int j;
+
+ for (j = 0; j < c->argc; j++)
+ decrRefCount(c->argv[j]);
+ zfree(c->argv);
+}
+
void freeFakeClient(struct redisClient *c) {
sdsfree(c->querybuf);
listRelease(c->reply);
@@ -639,14 +647,30 @@ int loadAppendOnlyFile(char *filename) {
if (argc < 1) goto fmterr;
argv = zmalloc(sizeof(robj*)*argc);
+ fakeClient->argc = argc;
+ fakeClient->argv = argv;
+
for (j = 0; j < argc; j++) {
- if (fgets(buf,sizeof(buf),fp) == NULL) goto readerr;
+ if (fgets(buf,sizeof(buf),fp) == NULL) {
+ fakeClient->argc = j; /* Free up to j-1. */
+ freeFakeClientArgv(fakeClient);
+ goto readerr;
+ }
if (buf[0] != '$') goto fmterr;
len = strtol(buf+1,NULL,10);
argsds = sdsnewlen(NULL,len);
- if (len && fread(argsds,len,1,fp) == 0) goto readerr;
+ if (len && fread(argsds,len,1,fp) == 0) {
+ sdsfree(argsds);
+ fakeClient->argc = j; /* Free up to j-1. */
+ freeFakeClientArgv(fakeClient);
+ goto readerr;
+ }
argv[j] = createObject(REDIS_STRING,argsds);
- if (fread(buf,2,1,fp) == 0) goto readerr; /* discard CRLF */
+ if (fread(buf,2,1,fp) == 0) {
+ fakeClient->argc = j+1; /* Free up to j. */
+ freeFakeClientArgv(fakeClient);
+ goto readerr; /* discard CRLF */
+ }
}
/* Command lookup */
@@ -655,9 +679,8 @@ int loadAppendOnlyFile(char *filename) {
redisLog(REDIS_WARNING,"Unknown command '%s' reading the append only file", (char*)argv[0]->ptr);
exit(1);
}
+
/* Run the command in the context of a fake client */
- fakeClient->argc = argc;
- fakeClient->argv = argv;
cmd->proc(fakeClient);
/* The fake client should not have a reply */
@@ -667,9 +690,7 @@ int loadAppendOnlyFile(char *filename) {
/* Clean up. Command code may have changed argv/argc so we use the
* argv/argc of the client instead of the local variables. */
- for (j = 0; j < fakeClient->argc; j++)
- decrRefCount(fakeClient->argv[j]);
- zfree(fakeClient->argv);
+ freeFakeClientArgv(fakeClient);
}
/* This point can only be reached when EOF is reached without errors.