aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-06 22:28:57 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-06 22:28:57 +0000
commit700312b11f62815e9455ea5b898ec4046eddee99 (patch)
tree1987188276d9d1e8e1113993a620e92ec5e6ae2f /channels/chan_sip.c
parent8ef479953a87eab3b9424e0e89b72f027556c2d9 (diff)
(closes issue #9724, closes issue #10374)
Reported by: kenw Patches: 9724.txt uploaded by russell (license 2) Tested by: kenw, russell Resolve a deadlock that occurs when doing a SIP transfer to parking. I come across this type of deadlock fairly often it seems. It is very important to mind the boundary between the channel driver and the core in respect to the channel lock and the channel-pvt lock. Channel drivers lock to lock the pvt and then the channel once it calls into the core, while the core will do it in the opposite order. The way this is avoided is by having channel drivers either release their pvt lock while calling into the core, or such as in this case, unlocking the pvt just long enough to acquire the channel lock. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@81832 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index b31d456c1..d44910251 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -12873,8 +12873,17 @@ static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct
transferer->readformat = chan2->readformat;
transferer->writeformat = chan2->writeformat;
- /* Prepare for taking over the channel */
+ /* Prepare for taking over the channel. Go ahead and grab this channel
+ * lock here to avoid a deadlock with callbacks into the channel driver
+ * that hold the channel lock and want the pvt lock. */
+ while (ast_channel_trylock(chan2)) {
+ struct sip_pvt *pvt = chan2->tech_pvt;
+ ast_mutex_unlock(&pvt->lock);
+ usleep(1);
+ ast_mutex_lock(&pvt->lock);
+ }
ast_channel_masquerade(transferer, chan2);
+ ast_channel_unlock(chan2);
/* Setup the extensions and such */
ast_copy_string(transferer->context, chan2->context, sizeof(transferer->context));