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

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