summaryrefslogtreecommitdiff
path: root/main/bridge.c
diff options
context:
space:
mode:
authorKevin Harwell <kharwell@digium.com>2017-06-20 16:05:08 -0500
committerKevin Harwell <kharwell@digium.com>2017-06-21 16:18:13 -0500
commit27dae55fb6bf802befe6f398d02f278f2c31114c (patch)
treeec5d10c92d43dde00d95856bb7d99c0304c1f07d /main/bridge.c
parent0c0d69d4f38756c2f83d2c9007033e0ca05652c4 (diff)
core_local: local channel data not being properly unref'ed and unlocked
In an earlier version of Asterisk a local channel [un]lock all functions were added in order to keep a crash from occurring when a channel hung up too early during an attended transfer. Unfortunately, when a transfer failure occurs and depending on the timing, the local channels sometime do not get properly unlocked and deref'ed after being locked and ref'ed. This happens because the underlying local channel structure gets NULLed out before unlocking. This patch reworks those [un]lock functions and makes sure the values that get locked and ref'ed later get unlocked and deref'ed. ASTERISK-27074 #close Change-Id: Ice96653e29bd9d6674ed5f95feb6b448ab148b09
Diffstat (limited to 'main/bridge.c')
-rw-r--r--main/bridge.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/main/bridge.c b/main/bridge.c
index 8cde62cb5..8902145cf 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -4276,14 +4276,15 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
if (bridge2) {
+ void *tech;
struct ast_channel *locals[2];
/* Have to lock everything just in case a hangup comes in early */
- ast_local_lock_all(local_chan, &locals[0], &locals[1]);
+ ast_local_lock_all(local_chan, &tech, &locals[0], &locals[1]);
if (!locals[0] || !locals[1]) {
ast_log(LOG_ERROR, "Transfer failed probably due to an early hangup - "
"missing other half of '%s'\n", ast_channel_name(local_chan));
- ast_local_unlock_all(local_chan);
+ ast_local_unlock_all(tech, locals[0], locals[1]);
ao2_cleanup(local_chan);
return AST_BRIDGE_TRANSFER_FAIL;
}
@@ -4294,7 +4295,7 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
}
ast_attended_transfer_message_add_link(transfer_msg, locals);
- ast_local_unlock_all(local_chan);
+ ast_local_unlock_all(tech, locals[0], locals[1]);
} else {
ast_attended_transfer_message_add_app(transfer_msg, app, local_chan);
}