diff options
author | Matthew Jordan <mjordan@digium.com> | 2012-01-13 16:48:06 +0000 |
---|---|---|
committer | Matthew Jordan <mjordan@digium.com> | 2012-01-13 16:48:06 +0000 |
commit | a8276fe8efbca7e14862c469c0c95df71b506947 (patch) | |
tree | 8f777b718c107a4ba51c9f9fe93e347545e64ad2 /main/bridging.c | |
parent | 19a976108479e82e6d6d9eadae2e7cc20a98a0ac (diff) |
Fix crash from bridge channel hangup race condition in ConfBridge
This patch addresses two issues in ConfBridge and the channel bridge layer:
1. It fixes a race condition wherein the bridge channel could be hung up
2. It removes the deadlock avoidance from the bridging layer and makes the
bridge_pvt an ao2 ref counted object
Patch by David Vossel (mjordan was merely the commit monkey)
(issue ASTERISK-18988)
(closes issue ASTERISK-18885)
Reported by: Dmitry Melekhov
Tested by: Matt Jordan
Patches: chan_bridge_cleanup_v.diff uploaded by David Vossel (license 5628)
(closes issue ASTERISK-19100)
Reported by: Matt Jordan
Tested by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/1654/
........
Merged revisions 350550 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@350551 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/bridging.c')
-rw-r--r-- | main/bridging.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/main/bridging.c b/main/bridging.c index abf5a0386..b97150f04 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -1121,7 +1121,7 @@ static void *bridge_channel_thread(void *data) state = bridge_channel_join(bridge_channel); /* If no other thread is going to take the channel then hang it up, or else we would have to service it until something else came along */ - if (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP) { + if (bridge_channel->allow_impart_hangup && (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP)) { ast_hangup(bridge_channel->chan); } @@ -1137,7 +1137,7 @@ static void *bridge_channel_thread(void *data) return NULL; } -int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features) +int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, int allow_hangup) { struct ast_bridge_channel *bridge_channel = bridge_channel_alloc(bridge); /* Try to allocate a structure for the bridge channel */ @@ -1149,6 +1149,8 @@ int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struc bridge_channel->chan = chan; bridge_channel->swap = swap; bridge_channel->features = features; + bridge_channel->allow_impart_hangup = allow_hangup; + /* Actually create the thread that will handle the channel */ if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) { |