From 5e412586e54d0a68c6a4978ddc5f52cae177171f Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Fri, 17 Jul 2026 14:33:49 +0200 Subject: [PATCH] MT#65511 AmB2BSession: `media_session` clean in destructor Normal shutdown already triggers the `clearRtpReceiverRelay()` in `AmB2BSession::onBeforeDestroy()`, so the destructor should actually normally see `media_session` ptr nulled. But it seems in some of the fork/transfer related scenarios this doesn't happen. So adding the defensive clean-up on the same manner the destructor of the `CallLeg` has (it uses the `releaseMediaSession()`, which is essentially the same: `stop()`; `releaseReference()` and NULLing), makes it consistent with these other_legs cleanup. The main reason is caused by a call leg (`AmB2BSession`), which was freed while the `AmB2BMedia::a` / `AmB2BMedia::b` still points to it. In this case we can crash during the media-thread DTMF processing. This fix is a hardening rather than a fix of the root cause. The root cause still is related to the cleanup path: certain call leg gets torn down through the path that skips (or maybe even races) the normal `onBeforeDestroy()`/`clearRtpReceiverRelay()` cleanup, leaving its shared `AmB2BMedia` with a dangling `a` or `b` pointer. Meanwhile the `a` / `b` are raw, non-owned pointers, which may remain dangling. Change-Id: Ia1ee42a27014d2086b37a787f8555e6d7681d4a8 --- core/AmB2BSession.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/AmB2BSession.cpp b/core/AmB2BSession.cpp index ac1a83a4..680f5cd3 100644 --- a/core/AmB2BSession.cpp +++ b/core/AmB2BSession.cpp @@ -127,6 +127,17 @@ AmB2BSession::~AmB2BSession() { ILOG_DLG(L_DBG, "relayed_req.size() = %zu\n",relayed_req.size()); + /* defensive release of the primary media_session, for the case when + * some fork/transfer path forgets to call clearRtpReceiverRelay(), + * the media_session ptr still gets nulled out before the object's memory is released. + */ + if (media_session) { + ILOG_DLG(L_ERR, "This media_session was not released before AmB2BSession destruction! Do it now.\n"); + media_session->stop(a_leg); + media_session->releaseReference(); + media_session = NULL; + } + map::iterator it = recvd_req.begin(); ILOG_DLG(L_DBG, "recvd_req.size() = %zu\n",recvd_req.size()); for(;it != recvd_req.end(); ++it){ @@ -137,7 +148,7 @@ AmB2BSession::~AmB2BSession() delete subs; } -void AmB2BSession::set_sip_relay_only(bool r) { +void AmB2BSession::set_sip_relay_only(bool r) { if (!getLocalTag().empty()) ILOG_DLG(L_DBG, "Set sip_relay_only=%s for local_tag '%s'\n", (r ? "true" : "false"), getLocalTag().c_str());