diff options
author | David Vossel <dvossel@digium.com> | 2011-11-10 21:56:16 +0000 |
---|---|---|
committer | David Vossel <dvossel@digium.com> | 2011-11-10 21:56:16 +0000 |
commit | 0a2a79c94bb402cdd0b3f6388f931243fb51b6cb (patch) | |
tree | 6a60bbaefbf36da6bfb43cf8453d619bcd199560 /main/bridging.c | |
parent | dc05ce5e4f8ee8f5080b16d33728441c68482bb8 (diff) |
Merged revisions 344493 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
........
r344493 | dvossel | 2011-11-10 15:54:42 -0600 (Thu, 10 Nov 2011) | 12 lines
Fixes issue with ConfBridge participants hanging up during DTMF feature menu usage getting stuck in conference forever.
When a conference user enters the DTMF menu they are suspended from the
bridge while the channel is handed off to the DTMF feature code. If a
user entered this state and hungup, there existed a race condition where
the channel could not exit the conference because it was waiting on a
signal that would never arrive. This patch fixes that, because it would
stupid for me to talk about the problem and commit a patch for something else.
(closes issue ASTERISK-18829)
Reported by: zvision
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@344494 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/bridging.c')
-rw-r--r-- | main/bridging.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/main/bridging.c b/main/bridging.c index dea4f77a0..503e86509 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -739,12 +739,13 @@ static enum ast_bridge_channel_state bridge_channel_join_multithreaded(struct as ao2_unlock(bridge_channel->bridge); + ao2_lock(bridge_channel); /* Wait for data to either come from the channel or us to be signalled */ if (!bridge_channel->suspended) { + ao2_unlock(bridge_channel); ast_debug(10, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms); } else { - ao2_lock(bridge_channel); ast_debug(10, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel)); ao2_unlock(bridge_channel); @@ -777,9 +778,10 @@ static enum ast_bridge_channel_state bridge_channel_join_singlethreaded(struct a /*! \brief Internal function that suspends a channel from a bridge */ static void bridge_channel_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) { + ao2_lock(bridge_channel); bridge_channel->suspended = 1; - bridge_array_remove(bridge, bridge_channel->chan); + ao2_unlock(bridge_channel); if (bridge->technology->suspend) { bridge->technology->suspend(bridge, bridge_channel); @@ -791,14 +793,18 @@ static void bridge_channel_suspend(struct ast_bridge *bridge, struct ast_bridge_ /*! \brief Internal function that unsuspends a channel from a bridge */ static void bridge_channel_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) { - bridge_channel->suspended =0; - + ao2_lock(bridge_channel); + bridge_channel->suspended = 0; bridge_array_add(bridge, bridge_channel->chan); + ast_cond_signal(&bridge_channel->cond); + ao2_unlock(bridge_channel); if (bridge->technology->unsuspend) { bridge->technology->unsuspend(bridge, bridge_channel); } + + return; } @@ -865,6 +871,12 @@ static void bridge_channel_feature(struct ast_bridge *bridge, struct ast_bridge_ /* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */ if (hook) { hook->callback(bridge, bridge_channel, hook->hook_pvt); + /* If we are handing the channel off to an external hook for ownership, + * we are not guaranteed what kind of state it will come back in. If + * the channel hungup, we need to detect that here. */ + if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) { + ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END); + } } else { ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan); } |