From 4d77481ee19f620673f82ab465d811b6d8d76bb8 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 26 May 2011 16:34:42 -0400 Subject: [PATCH] freetdm: ISDN - Fix for segfault when we receive STA CFM while call is being cleared --- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c | 6 ++++++ .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c | 9 +++++++-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c | 4 ++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 0789c433f9..872cf51bc4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -881,6 +881,12 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) uint8_t call_state = 0; ISDN_FUNC_TRACE_ENTER(__FUNCTION__); + + if (!suInstId && !spInstId) { + /* We already cleared this call */ + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dropping STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); + return; + } if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) { call_state = staEvnt->callSte.callGlblSte.val; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 67de893f5d..2a523c7cb9 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -502,12 +502,16 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St sngisdn_event_data_t *sngisdn_event = NULL; ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - + + /* We sometimes receive a STA CFM after receiving a RELEASE/RELEASE COMPLETE, so we need to lock + here in case we are calling clear_call_data at the same time this function is called */ + + ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); + ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); return; } @@ -526,6 +530,7 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt)); ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); + ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 3ba776928d..61f340205d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -100,12 +100,12 @@ void clear_call_data(sngisdn_chan_data_t *sngisdn_info) ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex); g_sngisdn_data.ccs[cc_id].active_spInstIds[sngisdn_info->spInstId]=NULL; g_sngisdn_data.ccs[cc_id].active_suInstIds[sngisdn_info->suInstId]=NULL; - ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex); - + sngisdn_info->suInstId = 0; sngisdn_info->spInstId = 0; sngisdn_info->globalFlg = 0; sngisdn_info->flags = 0; + ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex); return; }