summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2014-12-18 15:05:49 +0000
committerMark Michelson <mmichelson@digium.com>2014-12-18 15:05:49 +0000
commitc1582929f9c27330ac58420e2329421a4713b70c (patch)
treedd35cbfb298678015e0243f6e61c760fd1bb13c7 /main
parent5bd5f580c13e5d96375a3aeeba1c2a0d3eeac17c (diff)
Prevent possible race condition on dual redirect of channels in the same bridge.
The AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT flag was created to prevent bridges from prematurely acting on orphaned channels in bridges. The problem with the AMI redirect action was that it was setting this flag on channels based on the presence of a PBX, not whether the channel was in a bridge. Whether a channel has a PBX is irrelevant, so the condition has been altered to check if the channel is in a bridge. ASTERISK-24536 #close Reported by Niklas Larsson Review: https://reviewboard.asterisk.org/r/4268 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@429741 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/manager.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/main/manager.c b/main/manager.c
index b00fa9263..b135d74d4 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -4526,6 +4526,8 @@ static int action_redirect(struct mansession *s, const struct message *m)
int pi = 0;
int pi2 = 0;
int res;
+ int chan1_wait = 0;
+ int chan2_wait = 0;
if (ast_strlen_zero(name)) {
astman_send_error(s, m, "Channel not specified");
@@ -4610,16 +4612,20 @@ static int action_redirect(struct mansession *s, const struct message *m)
}
/* Dual channel redirect in progress. */
- if (ast_channel_pbx(chan)) {
- ast_channel_lock(chan);
+ ast_channel_lock(chan);
+ if (ast_channel_is_bridged(chan)) {
ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
- ast_channel_unlock(chan);
+ chan1_wait = 1;
}
- if (ast_channel_pbx(chan2)) {
- ast_channel_lock(chan2);
+ ast_channel_unlock(chan);
+
+ ast_channel_lock(chan2);
+ if (ast_channel_is_bridged(chan2)) {
ast_set_flag(ast_channel_flags(chan2), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
- ast_channel_unlock(chan2);
+ chan2_wait = 1;
}
+ ast_channel_unlock(chan2);
+
res = ast_async_goto(chan, context, exten, pi);
if (!res) {
if (!ast_strlen_zero(context2)) {
@@ -4637,12 +4643,12 @@ static int action_redirect(struct mansession *s, const struct message *m)
}
/* Release the bridge wait. */
- if (ast_channel_pbx(chan)) {
+ if (chan1_wait) {
ast_channel_lock(chan);
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
ast_channel_unlock(chan);
}
- if (ast_channel_pbx(chan2)) {
+ if (chan2_wait) {
ast_channel_lock(chan2);
ast_clear_flag(ast_channel_flags(chan2), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
ast_channel_unlock(chan2);