mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-18 15:49:56 +00:00
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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user