diff --git a/src/controller/ha.c b/src/controller/ha.c index d2d878cc..aa7f84ea 100644 --- a/src/controller/ha.c +++ b/src/controller/ha.c @@ -56,14 +56,15 @@ int ha_init(ha_state_t *ha, const ha_config_t *cfg, int my_priority) if (!ha || !cfg) return -EINVAL; + /* Zero first so ha_fini() is safe even if validation fails below */ + memset(ha, 0, sizeof(*ha)); + if (cfg->heartbeat_interval_ms < 2000) return -EINVAL; if (cfg->heartbeat_timeout_ms < cfg->heartbeat_interval_ms) return -EINVAL; if (cfg->election_timeout_ms < 500) return -EINVAL; - - memset(ha, 0, sizeof(*ha)); ha->config = *cfg; ha->my_priority = my_priority; diff --git a/src/controller/testsuite/test_ha_role.c b/src/controller/testsuite/test_ha_role.c index 33e2036d..184870cd 100644 --- a/src/controller/testsuite/test_ha_role.c +++ b/src/controller/testsuite/test_ha_role.c @@ -138,13 +138,14 @@ static void test_heartbeat_stale_no_crash_without_primary(void) { ha_state_t ha; ha_config_t cfg = { - .heartbeat_interval_ms = 3000, - .heartbeat_timeout_ms = 100, /* very short for test */ + .heartbeat_interval_ms = 2000, /* minimum valid */ + .heartbeat_timeout_ms = 3000, /* >= interval */ .election_timeout_ms = 2000, .probe_connect_timeout_ms = 500, .max_promotion_retries = 5, }; - ha_init(&ha, &cfg, 0); + /* Staleness is injected manually below; timeout value only needs to be valid */ + TEST_ASSERT_EQUAL_INT(0, ha_init(&ha, &cfg, 0)); /* Set last_heartbeat to a time far in the past to simulate timeout */ clock_gettime(CLOCK_MONOTONIC, &ha.last_heartbeat); ha.last_heartbeat.tv_sec -= 10; /* 10 seconds ago */