From: Mark Michelson Date: Mon, 8 Jun 2009 17:35:58 +0000 (+0000) Subject: Recorded merge of revisions 199588 via svnmerge from X-Git-Tag: 1.6.1.3-rc1~172 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87eda713ad13ef1fec730905627c73be5e3b2aba;p=thirdparty%2Fasterisk.git 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.1@199590 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 3ba459e0eb..0e34997d5d 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -5302,6 +5302,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); @@ -5310,6 +5325,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) @@ -19263,6 +19279,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, @@ -19291,6 +19321,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) {