From d2f7b22640ee99d3dcb652135350277143754cdd Mon Sep 17 00:00:00 2001 From: agupta <abhay@avissol.com> Date: Thu, 6 Jun 2019 18:18:18 +0530 Subject: [PATCH] chan_pjsip.c: Check for channel and session to not be NULL in hangup We have seen some rare case of segmentation fault in hangup function and we could notice that channel pointer was NULL. Debug log shows that there is a 200 OK answer and SIP timeout at the same time. It looks that while the SIP session was being destroyed due to timeout call hangup due to answer event lead to race condition and channel is being destroyed from two different places. The check ensures we check it not to be NULL before freeing it. ASTERISK-25371 Change-Id: I19f6566830640625e08f7b87bfe15758ad33a778 --- channels/chan_pjsip.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index f2187efb29..e61a40828e 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -2336,18 +2336,27 @@ static int hangup(void *data) struct hangup_data *h_data = data; struct ast_channel *ast = h_data->chan; struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast); - struct ast_sip_session *session = channel->session; - int cause = h_data->cause; - /* - * It's possible that session_terminate might cause the session to be destroyed - * immediately so we need to keep a reference to it so we can NULL session->channel - * afterwards. + * Before cleaning we have to ensure that channel or its session is not NULL + * we have seen rare case when taskprocessor calls hangup but channel is NULL + * due to SIP session timeout and answer happening at the same time */ - ast_sip_session_terminate(ao2_bump(session), cause); - clear_session_and_channel(session, ast); - ao2_cleanup(session); - ao2_cleanup(channel); + if (channel) { + struct ast_sip_session *session = channel->session; + if (session) { + int cause = h_data->cause; + + /* + * It's possible that session_terminate might cause the session to be destroyed + * immediately so we need to keep a reference to it so we can NULL session->channel + * afterwards. + */ + ast_sip_session_terminate(ao2_bump(session), cause); + clear_session_and_channel(session, ast); + ao2_cleanup(session); + } + ao2_cleanup(channel); + } ao2_cleanup(h_data); return 0; } -- GitLab