summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSubhi Al Hasan <jodevsa@gmail.com>2023-04-04 10:53:57 +0200
committerGitHub <noreply@github.com>2023-04-04 11:53:57 +0300
commit74b29985ced0d185dd15bde9888f93608ba57c14 (patch)
tree5c0d7382224469f4cef4faa25cee7c5821ab6b61 /src
parente1da724117bb842c383e227e57b9c45331f430db (diff)
downloadredis-74b29985ced0d185dd15bde9888f93608ba57c14.tar.gz
check for known-slave in sentinel rewrite config (#11775)
Fix the following config file error ``` *** FATAL CONFIG FILE ERROR (Redis 6.2.7) *** Reading the configuration file, at line 152 >>> 'sentinel known-replica XXXX 127.0.0.1 5001' Duplicate hostname and port for replica. ``` that is happening when a user uses the legacy key "known-slave" in the config file and a config rewrite occurs. The config rewrite logic won't replace the old line "sentinel known-slave XXXX 127.0.0.1 5001" and would add a new line with "sentinel known-replica XXXX 127.0.0.1 5001" which results in the error above "Duplicate hostname and port for replica." example: Current sentinal.conf ``` ... sentinel known-slave XXXX 127.0.0.1 5001 sentinel example-random-option X ... ``` after the config rewrite logic runs: ``` .... sentinel known-slave XXXX 127.0.0.1 5001 sentinel example-random-option X # Generated by CONFIG REWRITE sentinel known-replica XXXX 127.0.0.1 5001 ``` This bug only exists in Redis versions >=6.2 because prior to that it was hidden by the effects of this bug https://github.com/redis/redis/issues/5388 that was fixed in https://github.com/redis/redis/pull/8271 and was released in versions >=6.2
Diffstat (limited to 'src')
-rw-r--r--src/config.c5
-rw-r--r--src/sentinel.c7
-rw-r--r--src/server.h2
3 files changed, 10 insertions, 4 deletions
diff --git a/src/config.c b/src/config.c
index 94fc039e2..9a3f8d969 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1221,7 +1221,7 @@ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
*
* "line" is either used, or freed, so the caller does not need to free it
* in any way. */
-void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) {
+int rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) {
sds o = sdsnew(option);
list *l = dictFetchValue(state->option_to_line,o);
@@ -1231,7 +1231,7 @@ void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *opti
/* Option not used previously, and we are not forced to use it. */
sdsfree(line);
sdsfree(o);
- return;
+ return 0;
}
if (l) {
@@ -1254,6 +1254,7 @@ void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *opti
rewriteConfigAppendLine(state,line);
}
sdsfree(o);
+ return 1;
}
/* Write the long long 'bytes' value as a string in a way that is parsable
diff --git a/src/sentinel.c b/src/sentinel.c
index b4dead7de..03482fdd2 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -2176,7 +2176,12 @@ void rewriteConfigSentinelOption(struct rewriteConfigState *state) {
line = sdscatprintf(sdsempty(),
"sentinel known-replica %s %s %d",
master->name, announceSentinelAddr(slave_addr), slave_addr->port);
- rewriteConfigRewriteLine(state,"sentinel known-replica",line,1);
+ /* try to replace any known-slave option first if found */
+ if (rewriteConfigRewriteLine(state, "sentinel known-slave", sdsdup(line), 0) == 0) {
+ rewriteConfigRewriteLine(state, "sentinel known-replica", line, 1);
+ } else {
+ sdsfree(line);
+ }
/* rewriteConfigMarkAsProcessed is handled after the loop */
}
dictReleaseIterator(di2);
diff --git a/src/server.h b/src/server.h
index dd50e9089..02ec91ee0 100644
--- a/src/server.h
+++ b/src/server.h
@@ -3171,7 +3171,7 @@ void loadServerConfig(char *filename, char config_from_stdin, char *options);
void appendServerSaveParams(time_t seconds, int changes);
void resetServerSaveParams(void);
struct rewriteConfigState; /* Forward declaration to export API. */
-void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force);
+int rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force);
void rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, const char *option);
int rewriteConfig(char *path, int force_write);
void initConfigValues();