fix(lib): detach the received packet before handing it to a vtask (bug-1916)
vtask_handle_msg published the VTASK_IO task while ep->fsm_in.pkt still pointed at the packet; INVOKE_MSG_HANDLER clears the slot only after the handler returns. A vtask could decode and free the packet (xce_decode) and wake the client, whose failover reconnect then ran endpoint_fini and freed the dangling slot again: ASAN heap-use-after-free in free_packet, seen in the worker and scheduler during failovers under heavy CPU load. vtask_handle_msg now clears ep->fsm_in.pkt before vtask_enq and marks the task the packet's sole owner (owns_io_pkt), so never-run tasks free it at vtaskmgr_fini and an enqueue failure frees it instead of leaking; xcectx vtask_entry frees it on its early -EINVAL exits. Same take-and- clear discipline the controller's peer-control path already used. Tests: test_vtask_pkt_handoff.c (3), RED reproduces the soak's ASAN stack. libxce 733/0; xce-build all green; loaded /xce-test-ha soak (8 rounds, 40 spinners) PASS with no ASAN reports (it crashed 2/2 before). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2aefa939db
commit
0fb2e14cc7
6 changed files with 257 additions and 17 deletions
|
|
@ -51,12 +51,14 @@ typedef struct {
|
|||
/* raft-drive-async task 3.1: when non-zero AND data->vtype == VTASK_IO, the
|
||||
* carried io_packet_t (data->u.iodata.pkt) is OWNED by the task and must be
|
||||
* freed by taskq_item_killer if the task is destroyed while still queued
|
||||
* (never executed) at vtaskmgr_fini. Default 0 preserves the legacy
|
||||
* endpoint-owned-packet model used by the libxce client path (xcectx.c's
|
||||
* vtask_handle_msg does NOT clear ep->fsm_in.pkt, so the packet lifetime is
|
||||
* tied to the endpoint, not the task — freeing it here would double-free).
|
||||
* The controller's peer-control dispatch sets this to 1 because it clears
|
||||
* ep->fsm_in.pkt and the task becomes the sole owner. */
|
||||
* (never executed) at vtaskmgr_fini. Both IO handoffs set it to 1 because
|
||||
* both clear ep->fsm_in.pkt and the task becomes the sole owner: the
|
||||
* controller's peer-control dispatch (ha.c) and, since bug-1916,
|
||||
* vtask_handle_msg (libxce client xcectx.c + controller cluster.c), which
|
||||
* used to leave ep->fsm_in.pkt naming a packet the task's xce_decode freed
|
||||
* until INVOKE_MSG_HANDLER cleared it after the handler returned — a window
|
||||
* in which endpoint_fini double-freed it. 0 only for tasks that do not
|
||||
* own a packet. */
|
||||
int owns_io_pkt;
|
||||
} vtask_t;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue