diff options
author | antirez <antirez@gmail.com> | 2014-09-05 15:14:36 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2014-09-08 10:56:52 +0200 |
commit | de663966c64e9f27e667ad6a0dacf66aaa8ad32e (patch) | |
tree | aed12296b0c0886c37d8061ec64c1063b1217acb /src/aof.c | |
parent | 132550efc32e9738ec31f552c899dd67b5551e10 (diff) | |
download | redis-de663966c64e9f27e667ad6a0dacf66aaa8ad32e.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.
Diffstat (limited to 'src/aof.c')
-rw-r--r-- | src/aof.c | 37 |
1 files changed, 29 insertions, 8 deletions
@@ -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. |