mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-02 19:16:15 +00:00
CHANNEL(peer), chan_iax2, res_fax, SNMP agent: Fix deadlock from reaching across a bridge.
Calling ast_channel_bridge_peer() cannot be done while holding any channel locks. The reported issue hit the deadlock in chan_iax2, but an audit of the ast_channel_bridge_peer() calls found three more locations where the same deadlock can occur. * Made CHANNEL(peer), res_fax, and the SNMP agent not call ast_channel_bridge_peer() with any channel locked. For CHANNEL(peer) I had to rework the logic to not hold the channel lock. * Made chan_iax2 no longer call ast_channel_bridge_peer(). It was done for legacy reasons that no longer apply. * Removed the iax.conf forcejitterbuffer option. It is now always enabled when the jitterbuffer option is enabled. If you put a jitter buffer on a channel it will be on the channel. ASTERISK-24600 #close Reported by: Jeff Collell Review: https://reviewboard.asterisk.org/r/4342/ ........ Merged revisions 430817 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@430819 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -514,22 +514,34 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
} else if (!strcasecmp(data, "peer")) {
|
||||
RAII_VAR(struct ast_channel *, p, NULL, ast_channel_cleanup);
|
||||
struct ast_channel *peer;
|
||||
|
||||
ast_channel_lock(chan);
|
||||
p = ast_channel_bridge_peer(chan);
|
||||
if (p || ast_channel_tech(chan)) /* dummy channel? if so, we hid the peer name in the language */
|
||||
ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
|
||||
else {
|
||||
/* a dummy channel can still pass along bridged peer info via
|
||||
the BRIDGEPEER variable */
|
||||
const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
|
||||
if (!ast_strlen_zero(pname))
|
||||
ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
|
||||
else
|
||||
buf[0] = 0;
|
||||
peer = ast_channel_bridge_peer(chan);
|
||||
if (peer) {
|
||||
/* Only real channels could have a bridge peer this way. */
|
||||
ast_channel_lock(peer);
|
||||
ast_copy_string(buf, ast_channel_name(peer), len);
|
||||
ast_channel_unlock(peer);
|
||||
ast_channel_unref(peer);
|
||||
} else {
|
||||
buf[0] = '\0';
|
||||
ast_channel_lock(chan);
|
||||
if (!ast_channel_tech(chan)) {
|
||||
const char *pname;
|
||||
|
||||
/*
|
||||
* A dummy channel can still pass along bridged peer info
|
||||
* via the BRIDGEPEER variable.
|
||||
*
|
||||
* A horrible kludge, but... how else?
|
||||
*/
|
||||
pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
|
||||
if (!ast_strlen_zero(pname)) {
|
||||
ast_copy_string(buf, pname, len);
|
||||
}
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
} else if (!strcasecmp(data, "uniqueid")) {
|
||||
locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
|
||||
} else if (!strcasecmp(data, "transfercapability")) {
|
||||
|
Reference in New Issue
Block a user