From 207b0bcaf5bc0e9de21e9aa1285f3f3ae546aa43 Mon Sep 17 00:00:00 2001 From: lmadsen Date: Fri, 25 Feb 2011 20:21:38 +0000 Subject: Update .version, ChangeLog, and merge patch from r308945 git-svn-id: http://svn.digium.com/svn/asterisk/tags/1.8.4-rc2@308988 f38db490-d61c-443f-a65b-d21fe96a405b --- .version | 2 +- ChangeLog | 8 ++++++++ channels/chan_sip.c | 35 +++++++++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/.version b/.version index fd69cca7c..5bd56677d 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -1.8.4-rc1 +1.8.4-rc2 diff --git a/ChangeLog b/ChangeLog index f248c0b3c..59793098d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-02-25 Leif Madsen + + * Asterisk 1.8.4-rc2 Released. + + * Fix Deadlock with attended transfer of SIP call + (Closes issue #18837. Reported, patched by alecdavis. Tested by + alecdavid, Irontec, ZX81, cmaj) + 2011-02-23 Leif Madsen * Asterisk 1.8.4-rc1 Released. diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 0465cfc4e..4637678b8 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -27613,7 +27613,20 @@ static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl) if (!p) { return -1; } + /* + * Lock both the pvt and it's owner safely. + */ sip_pvt_lock(p); + while (p->owner && ast_channel_trylock(p->owner)) { + sip_pvt_unlock(p); + usleep(1); + sip_pvt_lock(p); + } + + if (!p->owner) { + sip_pvt_unlock(p); + return 0; + } if (udptl) { ast_udptl_get_peer(udptl, &p->udptlredirip); } else { @@ -27632,6 +27645,7 @@ static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl) } /* Reset lastrtprx timer */ p->lastrtprx = p->lastrtptx = time(NULL); + ast_channel_unlock(p->owner); sip_pvt_unlock(p); return 0; } @@ -27748,12 +27762,25 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i if (!ast_bridged_channel(chan) && !sip_cfg.directrtpsetup) /* We are in early state */ return 0; - ast_channel_lock(chan); + /* + * Lock both the pvt and it's owner safely. + */ sip_pvt_lock(p); + while (p->owner && ast_channel_trylock(p->owner)) { + sip_pvt_unlock(p); + usleep(1); + sip_pvt_lock(p); + } + + if (!p->owner) { + sip_pvt_unlock(p); + return 0; + } + if (p->alreadygone) { /* If we're destroyed, don't bother */ + ast_channel_unlock(p->owner); sip_pvt_unlock(p); - ast_channel_unlock(chan); return 0; } @@ -27761,8 +27788,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i that are known to be behind a NAT, then stop the process now */ if (nat_active && !ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA_NAT)) { + ast_channel_unlock(p->owner); sip_pvt_unlock(p); - ast_channel_unlock(chan); return 0; } @@ -27804,8 +27831,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i } /* Reset lastrtprx timer */ p->lastrtprx = p->lastrtptx = time(NULL); + ast_channel_unlock(p->owner); sip_pvt_unlock(p); - ast_channel_unlock(chan); return 0; } -- cgit v1.2.3