From 2fd62e8da98b2f21bcbb14e6e72cd55ee83034df Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Mon, 8 Jun 2009 17:42:27 +0000 Subject: [PATCH] Recorded merge of revisions 199588 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ........ r199588 | mmichelson | 2009-06-08 12:32:04 -0500 (Mon, 08 Jun 2009) | 9 lines Fix a deadlock that could occur when setting rtp stats on SIP calls. (closes issue #15143) Reported by: cristiandimache Patches: 15143.patch uploaded by mmichelson (license 60) Tested by: cristiandimache ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.2@199591 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 11063242e7..1833aac5a9 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -5730,6 +5730,21 @@ static int sip_hangup(struct ast_channel *ast) char *videoqos = ""; char *textqos = ""; + /* We need to get the lock on bridge because ast_rtp_set_vars will attempt + * to lock the bridge. This may get hairy... + */ + while (bridge && ast_channel_trylock(bridge)) { + struct ast_channel *chan = p->owner; + sip_pvt_unlock(p); + do { + /* Use chan since p->owner could go NULL on us + * while p is unlocked + */ + CHANNEL_DEADLOCK_AVOIDANCE(chan); + } while (sip_pvt_trylock(p)); + bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; + } + if (p->rtp) ast_rtp_set_vars(oldowner, p->rtp); @@ -5738,6 +5753,7 @@ static int sip_hangup(struct ast_channel *ast) if (IS_SIP_TECH(bridge->tech) && q && q->rtp) ast_rtp_set_vars(bridge, q->rtp); + ast_channel_unlock(bridge); } if (p->vrtp) @@ -20159,6 +20175,20 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req) struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; char *videoqos, *textqos; + /* We need to get the lock on bridge because ast_rtp_set_vars will attempt + * to lock the bridge. This may get hairy... + */ + while (bridge && ast_channel_trylock(bridge)) { + ast_channel_unlock(p->owner); + do { + /* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */ + sip_pvt_unlock(p); + usleep(1); + sip_pvt_lock(p); + } while (p->owner && ast_channel_trylock(p->owner)); + bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; + } + if (p->rtp) { if (p->do_history) { char *audioqos, @@ -20187,6 +20217,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req) if (IS_SIP_TECH(bridge->tech) && q && q->rtp) ast_rtp_set_vars(bridge, q->rtp); + ast_channel_unlock(bridge); } if (p->vrtp) {