diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index b4f4c259c2b60b225095c623dc990b8a6dd541a8..8cf2a05b594b4a5889ad695207ad03fd2ce99a73 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -2085,13 +2085,21 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event) } } - // leaving channel with Ref > 2 cause it is not destroyed during hangup + // leaving channel with Ref > 2 cause it is not destroyed during hangup, Ref < 2 cause crash during hangup + // race condition during REFER on chan_voicemngr_attended_call_transfer, + // Ref = 1 during the hangup when this ref decrease happened before the unref from chan_voicemngr_attended_call_transfer while (2 < ao2_ref(chan, 0)) ao2_ref(chan, -1); + while (2 > ao2_ref(chan, 0)) // Add ref back in case of race condition happened. + ao2_ref(chan, +1); + ast_debug(3, "channel %s, Refs: %d\n", ast_channel_name(chan),ao2_ref(chan, 0)); struct ast_channel *bridged_chan = ast_channel_bridge_peer(chan); if (bridged_chan) { while (2 < ao2_ref(bridged_chan, 0)) ast_channel_unref(bridged_chan); + while (2 > ao2_ref(bridged_chan, 0)) // Add ref back in case of race condition happened. + ast_channel_ref(bridged_chan); + ast_debug(3, "channel %s, Refs: %d\n", ast_channel_name(bridged_chan),ao2_ref(bridged_chan, 0)); } if (res) {