From fa875c057851cdcdcb5a9d39b8d22e546d6d4b57 Mon Sep 17 00:00:00 2001 From: Tilghman Lesher <tilghman@meg.abyt.es> Date: Tue, 8 Apr 2008 15:48:58 +0000 Subject: [PATCH] Merged revisions 113348 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r113348 | tilghman | 2008-04-08 10:39:16 -0500 (Tue, 08 Apr 2008) | 7 lines Move check for still-bridged channels out a little further, to avoid possible deadlocks. (Closes issue #12252) Reported by: callguy Patches: 20080319__bug12252.diff.txt uploaded by Corydon76 (license 14) Tested by: callguy ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@113349 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index df80bc045b..6e60c4308d 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1741,7 +1741,7 @@ static int __sip_autodestruct(const void *data); static void sip_scheddestroy(struct sip_pvt *p, int ms); static int sip_cancel_destroy(struct sip_pvt *p); static struct sip_pvt *sip_destroy(struct sip_pvt *p); -static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist); +static int __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist); static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod); static void __sip_pretend_ack(struct sip_pvt *p); static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod); @@ -4275,11 +4275,22 @@ static void sip_registry_destroy(struct sip_registry *reg) } /*! \brief Execute destruction of SIP dialog structure, release memory */ -static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) +static int __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) { struct sip_pvt *cur, *prev = NULL; struct sip_pkt *cp; + /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ + if (p->rtp && ast_rtp_get_bridged(p->rtp)) { + ast_verbose("Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); + return -1; + } + + if (p->vrtp && ast_rtp_get_bridged(p->vrtp)) { + ast_verbose("Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); + return -1; + } + if (sip_debug_test_pvt(p)) ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); @@ -4319,15 +4330,10 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) AST_SCHED_DEL(sched, p->waitid); AST_SCHED_DEL(sched, p->autokillid); - /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ if (p->rtp) { - while (ast_rtp_get_bridged(p->rtp)) - usleep(1); ast_rtp_destroy(p->rtp); } if (p->vrtp) { - while (ast_rtp_get_bridged(p->vrtp)) - usleep(1); ast_rtp_destroy(p->vrtp); } if (p->trtp) { @@ -4382,7 +4388,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) dialoglist_unlock(); if (!cur) { ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", p->callid); - return; + return 0; } /* remove all current packets in this dialog */ @@ -4403,6 +4409,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) ast_string_field_free_memory(p); ast_free(p); + return 0; } /*! \brief update_call_counter: Handle call_limit for SIP users @@ -18497,9 +18504,9 @@ static void *do_monitor(void *data) } } +restartsearch: /* Check for dialogs needing to be killed */ dialoglist_lock(); -restartsearch: t = time(NULL); /* don't scan the dialogs list if it hasn't been a reasonable period of time since the last time we did it (when MWI is being sent, we can @@ -18509,7 +18516,6 @@ restartsearch: if (sip_pvt_trylock(dialog)) { dialoglist_unlock(); usleep(1); - dialoglist_lock(); goto restartsearch; } @@ -18521,6 +18527,8 @@ restartsearch: if (dialog->needdestroy && !dialog->packets && !dialog->owner) { sip_pvt_unlock(dialog); __sip_destroy(dialog, TRUE, FALSE); + dialoglist_unlock(); + usleep(1); goto restartsearch; } sip_pvt_unlock(dialog); @@ -21606,13 +21614,20 @@ static int unload_module(void) monitor_thread = AST_PTHREADT_STOP; ast_mutex_unlock(&monlock); +restartdestroy: dialoglist_lock(); /* Destroy all the dialogs and free their memory */ p = dialoglist; while (p) { pl = p; p = p->next; - __sip_destroy(pl, TRUE, TRUE); + if (__sip_destroy(pl, TRUE, TRUE) < 0) { + /* Something is still bridged, let it react to getting a hangup */ + dialoglist = p; + dialoglist_unlock(); + usleep(1); + goto restartdestroy; + } } dialoglist = NULL; dialoglist_unlock(); -- GitLab