feat(ha): reference-counted ha_elect_ctx_t lifecycle (ha-elect-ctx-lifecycle)
Replace the deliberate election-carrier leak with an atomic refcount: a bias reference held by ha->elect_ctx plus one reference per captured vote endpoint, released via a new endpoint_t.on_fini teardown-completion hook (fired once, before ep->data is freed). Both real-election and PreVote capture sites (raft_cb_send_vote_request, raft_cb_send_pre_vote_request) increment on capture; both publish sites (ha_start_election_async, ha_start_prevote_async) now atomic_exchange the outgoing carrier and release it instead of leaking or freeing outright, so a still-outstanding vote endpoint keeps the superseded carrier alive until its own teardown completes. Verified: 758+ controller tests green, isolated LeakSanitizer run shows zero ha_elect_ctx_t leaks across many election/PreVote rounds, no premature-free/UAF under supersession, and a live 10-round HA soak (36 jobs, zero loss, all 3 nodes served as primary).
This commit is contained in:
parent
58e047f533
commit
6529dcf08f
14 changed files with 879 additions and 22 deletions
|
|
@ -101,6 +101,13 @@ typedef struct endpoint_t {
|
|||
time_t ts_last_in;
|
||||
time_t ts_last_out;
|
||||
void (*on_connected)(struct endpoint_t *ep); /* fire-once; called in iomgr thread after ssl_handshake_done=1 */
|
||||
/* ha-elect-ctx-lifecycle task 1.1: fire-once completion-side counterpart
|
||||
* to on_connected — called by endpoint_fini() immediately before it frees
|
||||
* ep->data, so a consumer can observe teardown completion (e.g. release a
|
||||
* reference a struct pointed to by ep->data was holding) while ep->data is
|
||||
* still valid. Does not change endpoint_fini's teardown ordering/timing —
|
||||
* it only adds an observation point at the existing free. */
|
||||
void (*on_fini)(struct endpoint_t *ep);
|
||||
/* bug-1298: reference count governing the lifetime of a HEAP-allocated
|
||||
* endpoint (endpoint_get). An ep is fini'd + freed exactly when refcnt
|
||||
* drops to 0. Holders: the creator/owner (endpoint_get sets refcnt=1, the
|
||||
|
|
@ -176,6 +183,7 @@ extern int endpoint_set_owner(endpoint_t*, void*);
|
|||
extern int endpoint_set_msg_handler(endpoint_t*, msg_handler_t);
|
||||
extern int endpoint_set_err_handler(endpoint_t*, err_handler_t);
|
||||
extern int endpoint_set_on_connected(endpoint_t*, void (*cb)(endpoint_t *));
|
||||
extern int endpoint_set_on_fini(endpoint_t*, void (*cb)(endpoint_t *));
|
||||
extern void endpoint_fini(endpoint_t*);
|
||||
/* bug-1298: endpoint refcount. endpoint_ref takes a reference; endpoint_unref
|
||||
* drops one and, when the last reference is released, fini's the ep and (for
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue