Skip to content

Commit d8c7db1

Browse files
committed
Improve RDB error-on-load handling
Previouly if we loaded a corrupt RDB, Redis printed an error report with a big "REPORT ON GITHUB" message at the bottom. But, we know RDB load failures are corrupt data, not corrupt code. Now when RDB failure is detected (duplicate keys or unknown data types in the file), we run check-rdb against the RDB then exit. The automatic check-rdb hopefully gives the user instant feedback about what is wrong instead of providing a mysterious stack trace.
1 parent 764b000 commit d8c7db1

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

src/rdb.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
#define RDB_LOAD_ENC (1<<0)
4545
#define RDB_LOAD_PLAIN (1<<1)
4646

47+
#define rdbExitReportCorruptRDB(reason) rdbCheckThenExit(reason, __LINE__);
48+
49+
void rdbCheckThenExit(char *reason, int where) {
50+
redisLog(REDIS_WARNING, "Corrupt RDB detected at rdb.c:%d (%s). "
51+
"Running 'redis-check-rdb --dbfilename %s'",
52+
where, reason, server.rdb_filename);
53+
redis_check_rdb(server.rdb_filename);
54+
exit(1);
55+
}
56+
4757
static int rdbWriteRaw(rio *rdb, void *p, size_t len) {
4858
if (rdb && rioWrite(rdb,p,len) == 0)
4959
return -1;
@@ -188,7 +198,7 @@ void *rdbLoadIntegerObject(rio *rdb, int enctype, int flags) {
188198
val = (int32_t)v;
189199
} else {
190200
val = 0; /* anti-warning */
191-
redisPanic("Unknown RDB integer encoding type");
201+
rdbExitReportCorruptRDB("Unknown RDB integer encoding type");
192202
}
193203
if (plain) {
194204
char buf[REDIS_LONGSTR_SIZE], *p;
@@ -394,7 +404,7 @@ void *rdbGenericLoadStringObject(rio *rdb, int flags) {
394404
case REDIS_RDB_ENC_LZF:
395405
return rdbLoadLzfStringObject(rdb,flags);
396406
default:
397-
redisPanic("Unknown RDB encoding type");
407+
rdbExitReportCorruptRDB("Unknown RDB encoding type");
398408
}
399409
}
400410

@@ -923,7 +933,7 @@ void rdbRemoveTempFile(pid_t childpid) {
923933
/* Load a Redis object of the specified type from the specified file.
924934
* On success a newly allocated object is returned, otherwise NULL. */
925935
robj *rdbLoadObject(int rdbtype, rio *rdb) {
926-
robj *o, *ele, *dec;
936+
robj *o = NULL, *ele, *dec;
927937
size_t len;
928938
unsigned int i;
929939

@@ -1078,7 +1088,9 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
10781088

10791089
/* Add pair to hash table */
10801090
ret = dictAdd((dict*)o->ptr, field, value);
1081-
redisAssert(ret == DICT_OK);
1091+
if (ret == DICT_ERR) {
1092+
rdbExitReportCorruptRDB("Duplicate keys detected");
1093+
}
10821094
}
10831095

10841096
/* All pairs should be read by now */
@@ -1164,11 +1176,11 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
11641176
hashTypeConvert(o, REDIS_ENCODING_HT);
11651177
break;
11661178
default:
1167-
redisPanic("Unknown encoding");
1179+
rdbExitReportCorruptRDB("Unknown encoding");
11681180
break;
11691181
}
11701182
} else {
1171-
redisPanic("Unknown object type");
1183+
rdbExitReportCorruptRDB("Unknown object type");
11721184
}
11731185
return o;
11741186
}

0 commit comments

Comments
 (0)