`switch_core_session_thread_pool_launch()` allocated the thread data (`td`)
from the session pool. However, `switch_core_session_thread()` destroys
the session pool before returning, leaving td as a dangling pointer.
The worker then accesses `td->running` and `td->pool` — a use-after-free
that crashes under memory pressure when the freed pool is reused.
Allocate `td` with `switch_zmalloc()` and set `td->alloc = 1` so the worker frees it
after the task completes. This ensures `td` outlives the session pool
destruction.
} else {
switch_set_flag(session, SSF_THREAD_RUNNING);
switch_set_flag(session, SSF_THREAD_STARTED);
- td = switch_core_session_alloc(session, sizeof(*td));
+ switch_zmalloc(td, sizeof(*td));
+ td->alloc = 1;
td->obj = session;
td->func = switch_core_session_thread;
status = switch_queue_push(session_manager.thread_queue, td);