Fix RDB check regression caused by PR 12022 (#12051)

The nightly tests showed that the recent PR #12022 caused random failures
in aof.tcl on checking RDB preamble inside an AOF file.

Root cause:
When checking RDB preamble in an AOF file, what's passed into redis_check_rdb is
aof_filename, not aof_filepath. The newly introduced isFifo function does not check return
status of the stat call and hence uses the uninitailized stat_p object.

Fix:
1. Fix isFifo by checking stat call's return code.
2. Pass aof_filepath instead of aof_filename to redis_check_rdb.
3. move the FIFO check to rdb.c since the limitation is the re-opening of the file, and not
  anything specific about redis-check-rdb.
This commit is contained in:
Joe Hu 2023-04-17 14:05:36 -04:00 committed by GitHub
parent e7f18432b8
commit 644d94558a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 14 additions and 13 deletions

View File

@ -697,3 +697,9 @@ int anetSetSockMarkId(char *err, int fd, uint32_t id) {
return ANET_OK;
#endif
}
int anetIsFifo(char *filepath) {
struct stat sb;
if (stat(filepath, &sb) == -1) return 0;
return S_ISFIFO(sb.st_mode);
}

View File

@ -70,5 +70,6 @@ int anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);
int anetPipe(int fds[2], int read_flags, int write_flags);
int anetSetSockMarkId(char *err, int fd, uint32_t id);
int anetGetError(int fd);
int anetIsFifo(char *filepath);
#endif

View File

@ -88,6 +88,11 @@ void rdbReportError(int corruption_error, int linenum, char *reason, ...) {
/* If we're loading an rdb file form disk, run rdb check (and exit) */
serverLog(LL_WARNING, "%s", msg);
char *argv[2] = {"",rdbFileBeingLoaded};
if (anetIsFifo(argv[1])) {
/* Cannot check RDB FIFO because we cannot reopen the FIFO and check already streamed data. */
rdbCheckError("Cannot check RDB that is a FIFO: %s", argv[1]);
return;
}
redis_check_rdb_main(2,argv,NULL);
} else if (corruption_error) {
/* In diskless loading, in case of corrupt file, log and exit. */

View File

@ -242,7 +242,7 @@ int checkSingleAof(char *aof_filename, char *aof_filepath, int last_file, int fi
}
if (preamble) {
char *argv[2] = {NULL, aof_filename};
char *argv[2] = {NULL, aof_filepath};
if (redis_check_rdb_main(2, argv, fp) == C_ERR) {
printf("RDB preamble of AOF file is not sane, aborting.\n");
exit(1);

View File

@ -186,15 +186,9 @@ void rdbCheckSetupSignals(void) {
sigaction(SIGABRT, &act, NULL);
}
static int isFifo(char *filename) {
struct stat stat_p;
stat(filename, &stat_p);
return S_ISFIFO(stat_p.st_mode);
}
/* Check the specified RDB file. Return 0 if the RDB looks sane, otherwise
* 1 is returned.
* The file is specified as a filename in 'rdbfilename' if 'fp' is not NULL,
* The file is specified as a filename in 'rdbfilename' if 'fp' is NULL,
* otherwise the already open file 'fp' is checked. */
int redis_check_rdb(char *rdbfilename, FILE *fp) {
uint64_t dbid;
@ -205,11 +199,6 @@ int redis_check_rdb(char *rdbfilename, FILE *fp) {
static rio rdb; /* Pointed by global struct riostate. */
struct stat sb;
if (isFifo(rdbfilename)) {
/* Cannot check RDB over named pipe because fopen blocks until another process opens the FIFO for writing. */
return 1;
}
int closefile = (fp == NULL);
if (fp == NULL && (fp = fopen(rdbfilename,"r")) == NULL) return 1;