Check for duplicate nodeids when loading nodes.conf (#2852)

For corrupted (human-made) or program-error-recovered nodes.conf files,
check for duplicate nodeids when loading nodes.conf. If a duplicate is
found, panic is triggered to prevent nodes from starting up
unexpectedly.

The node ID is used to identify every node across the whole cluster,
we do not expect to find duplicate nodeids in nodes.conf.

Signed-off-by: Binbin <binloveplay1314@qq.com>
This commit is contained in:
Binbin 2025-12-17 11:23:38 +08:00 committed by GitHub
parent 6b60e6bfc7
commit 8ab0152bef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 15 additions and 0 deletions

View File

@ -610,6 +610,7 @@ int clusterLoadConfig(char *filename) {
struct stat sb;
char *line;
int maxline, j;
dict *tmp_cluster_nodes;
if (fp == NULL) {
if (errno == ENOENT) {
@ -640,6 +641,7 @@ int clusterLoadConfig(char *filename) {
* To simplify we allocate 1024+CLUSTER_SLOTS*128 bytes per line. */
maxline = 1024 + CLUSTER_SLOTS * 128;
line = zmalloc(maxline);
tmp_cluster_nodes = dictCreate(&clusterNodesDictType);
while (fgets(line, maxline, fp) != NULL) {
int argc, aux_argc;
sds *argv, *aux_argv;
@ -687,6 +689,17 @@ int clusterLoadConfig(char *filename) {
if (!n) {
n = createClusterNode(argv[0], 0);
clusterAddNode(n);
dictAdd(tmp_cluster_nodes, sdsnewlen(argv[0], sdslen(argv[0])), NULL);
} else {
/* Check if the node (nodeid) has already been loaded. The nodeid is used to
* identify every node across the entire cluster, we do not expect to find
* duplicate nodeids in nodes.conf. */
dictEntry *de = dictFind(tmp_cluster_nodes, argv[0]);
if (de != NULL) {
serverLog(LL_WARNING, "Duplicate nodeid detected: %s", argv[0]);
sdsfreesplitres(argv, argc);
goto fmterr;
}
}
/* Format for the node address and auxiliary argument information:
* ip:port[@cport][,hostname][,aux=val]*] */
@ -943,6 +956,8 @@ int clusterLoadConfig(char *filename) {
zfree(line);
fclose(fp);
serverAssert(tmp_cluster_nodes != NULL);
dictRelease(tmp_cluster_nodes);
serverLog(LL_NOTICE, "Node configuration loaded, I'm %.40s", myself->name);