From 93b8616f1197dda2c4b5e7477eaff07ffbb51044 Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Wed, 13 May 2026 17:32:32 +0000 Subject: [PATCH] fix: capture am_i_primary() result once; set ha->role before phase2; cluster_init wrapper cleanup on failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - myapp.c: capture am_i_primary() into is_primary (avoids redundant second probe call); after load_primary_config() succeeds, record CTRL_PRIMARY role via atomic_store_explicit so cluster_init_phase2() sees the correct role (ha_init() defaults to CTRL_STANDBY) - myapp.c: add #include "ha.h" for CTRL_PRIMARY, atomic_store_explicit, and memory_order_release - cluster.c: cluster_init() wrapper now calls cluster_fini(c) before returning on create_ssl_context failure, hook failure, and cluster_init_phase2 failure — prevents SSL ctx and phase1 resource leak --- src/controller/cluster.c | 12 ++++++++++-- src/controller/myapp.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/controller/cluster.c b/src/controller/cluster.c index d8667d30..02fd0a1c 100644 --- a/src/controller/cluster.c +++ b/src/controller/cluster.c @@ -785,6 +785,7 @@ int cluster_init(cluster_t* c) c->myconf->keyfile); if (ssl_ctx == NULL) { ERROR("create_ssl_context failed"); + cluster_fini(c); return -errno; } c->ha.ssl_ctx = ssl_ctx; @@ -794,11 +795,18 @@ int cluster_init(cluster_t* c) if (c->myconf->cluster_config == NULL) { rc = xce_run_hooks(&(c->hooksys), XCE_CONTROLLER_HOOK_CLUSTER, HOOK_BEFORE_EVENT, HOOK_DETAIL_CLUSTER_INIT, c); - if (rc < 0) + if (rc < 0) { + cluster_fini(c); return rc; + } } - return cluster_init_phase2(c); + rc = cluster_init_phase2(c); + if (rc != 0) { + cluster_fini(c); + return rc; + } + return 0; } static int make_heartbeat(cluster_t* c, endpoint_t* ep) diff --git a/src/controller/myapp.c b/src/controller/myapp.c index 11ff22e4..bd642651 100644 --- a/src/controller/myapp.c +++ b/src/controller/myapp.c @@ -6,6 +6,7 @@ #include #include "cluster.h" +#include "ha.h" #include "myconf.h" #include "netio.h" #include "xce/cluster_def.h" @@ -43,8 +44,10 @@ int myapp_run(myconf_t* myconf) } c.ha.ssl_ctx = ssl_ctx; - /* Election: determine role before loading config */ - if (am_i_primary(&c)) { + /* Election: determine role before loading config. + * Capture result once — am_i_primary() probes peers and is expensive. */ + int is_primary = am_i_primary(&c); + if (is_primary) { /* Primary: load config from conf/current (FATAL if missing) */ rc = load_primary_config(&c); if (rc != 0) { @@ -52,6 +55,10 @@ int myapp_run(myconf_t* myconf) myconf_fini(myconf); return rc; } + /* Record election outcome so cluster_init_phase2() sees CTRL_PRIMARY. + * ha_init() unconditionally defaults ha->role to CTRL_STANDBY. */ + atomic_store_explicit(&c.ha.role, (int32_t)CTRL_PRIMARY, + memory_order_release); } else { /* Standby: fetch config from primary before Phase 2 */ rc = fetch_config_from_primary(&c); @@ -60,6 +67,7 @@ int myapp_run(myconf_t* myconf) myconf_fini(myconf); return rc; } + /* Role stays CTRL_STANDBY — already set by ha_init(). */ } /* Phase 2: full init (requires cluster_config) */