diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-06-08 05:18:22 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-06-08 05:18:22 +0000 |
commit | c88b7945f64ef713da3791e2518608c1e65e90de (patch) | |
tree | 26e5bf9e5c31678abc43f31da664b439ccfa0d1b /main | |
parent | 661f6d499e9e5c509d09d7775f64625b398143ac (diff) |
Fix a crash when a bridge switches from the softmix bridge technology to another.
A three party bridge uses the softmix bridging technology. This
technology has a dedicated thread used to perform the analog mixing. When
one of these parties leaves the bridge, the bridge technology is changed
from the softmix technology to a two-party mixing technology. Changing
technologies is done by removing channels from the old technology and
adding them to the new technology. Since the remaining channels do not
leave the bridge, the softmix mixing thread could continue to process all
channels in the bridge. If the bridge code is not able to start
destruction of the softmix technology before the softmix mixing thread
wakes up, a crash happens.
* Added a stop technology callback that technologies can use to request
any helper threads to stop in preparation for being destroyed.
(closes issue AST-1156)
Reported by: John Bigelow
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390975 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r-- | main/bridging.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/main/bridging.c b/main/bridging.c index 6a21c0b64..51f52c00e 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -1325,6 +1325,13 @@ static void destroy_bridge(void *obj) /* Pass off the bridge to the technology to destroy if needed */ if (bridge->technology) { + ast_debug(1, "Bridge %s: calling %s technology stop\n", + bridge->uniqueid, bridge->technology->name); + if (bridge->technology->stop) { + ast_bridge_lock(bridge); + bridge->technology->stop(bridge); + ast_bridge_unlock(bridge); + } ast_debug(1, "Bridge %s: calling %s technology destructor\n", bridge->uniqueid, bridge->technology->name); if (bridge->technology->destroy) { @@ -1743,6 +1750,12 @@ static int smart_bridge_operation(struct ast_bridge *bridge) return -1; } + ast_debug(1, "Bridge %s: calling %s technology stop\n", + dummy_bridge.uniqueid, old_technology->name); + if (old_technology->stop) { + old_technology->stop(&dummy_bridge); + } + /* Move existing channels over to the new technology. */ AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { if (bridge_channel->just_joined) { @@ -1782,11 +1795,11 @@ static int smart_bridge_operation(struct ast_bridge *bridge) */ if (old_technology->destroy) { ast_debug(1, "Bridge %s: deferring %s technology destructor\n", - bridge->uniqueid, old_technology->name); + dummy_bridge.uniqueid, old_technology->name); bridge_queue_action_nodup(bridge, deferred_action); } else { ast_debug(1, "Bridge %s: calling %s technology destructor\n", - bridge->uniqueid, old_technology->name); + dummy_bridge.uniqueid, old_technology->name); ast_module_unref(old_technology->mod); } |