fix: capture am_i_primary() result once; set ha->role before phase2; cluster_init wrapper cleanup on failure

- 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
This commit is contained in:
Rongsong Shen 2026-05-13 17:32:32 +00:00
parent 6b06aa02d9
commit 93b8616f11
2 changed files with 20 additions and 4 deletions

View file

@ -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)

View file

@ -6,6 +6,7 @@
#include <unistd.h>
#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) */