mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-07 18:38:02 +00:00
chan_iax2: Prevent deadlock due to duplicate autoservice.
If a switch is invoked using chan_iax2, deadlock can result because the PBX core is autoservicing the channel while chan_iax2 also then attempts to service it while waiting for the result of the switch. This removes servicing of the channel to prevent any conflicts. ASTERISK-30064 #close Change-Id: Ie92f206d32f9a36924af734ddde652b21106af22
This commit is contained in:
committed by
Kevin Harwell
parent
3b7bcbb6d5
commit
82cebaa023
@@ -14219,9 +14219,7 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
|
|||||||
{
|
{
|
||||||
struct iax2_dpcache *dp = NULL;
|
struct iax2_dpcache *dp = NULL;
|
||||||
struct timeval now = ast_tvnow();
|
struct timeval now = ast_tvnow();
|
||||||
int x, com[2], timeout, old = 0, outfd, doabort, callno;
|
int x, com[2], timeout, doabort, callno;
|
||||||
struct ast_channel *c = NULL;
|
|
||||||
struct ast_frame *f = NULL;
|
|
||||||
|
|
||||||
AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) {
|
AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) {
|
||||||
if (ast_tvcmp(now, dp->expiry) > 0) {
|
if (ast_tvcmp(now, dp->expiry) > 0) {
|
||||||
@@ -14268,8 +14266,8 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
|
|||||||
|
|
||||||
/* By here we must have a dp */
|
/* By here we must have a dp */
|
||||||
if (dp->flags & CACHE_FLAG_PENDING) {
|
if (dp->flags & CACHE_FLAG_PENDING) {
|
||||||
struct timeval start;
|
int res;
|
||||||
int ms;
|
struct pollfd pfd;
|
||||||
/* Okay, here it starts to get nasty. We need a pipe now to wait
|
/* Okay, here it starts to get nasty. We need a pipe now to wait
|
||||||
for a reply to come back so long as it's pending */
|
for a reply to come back so long as it's pending */
|
||||||
for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
|
for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
|
||||||
@@ -14290,35 +14288,31 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
|
|||||||
timeout = iaxdefaulttimeout * 1000;
|
timeout = iaxdefaulttimeout * 1000;
|
||||||
/* Temporarily unlock */
|
/* Temporarily unlock */
|
||||||
AST_LIST_UNLOCK(&dpcache);
|
AST_LIST_UNLOCK(&dpcache);
|
||||||
/* Defer any dtmf */
|
|
||||||
if (chan)
|
|
||||||
old = ast_channel_defer_dtmf(chan);
|
|
||||||
doabort = 0;
|
doabort = 0;
|
||||||
start = ast_tvnow();
|
|
||||||
while ((ms = ast_remaining_ms(start, timeout))) {
|
/* chan is in autoservice here, so do NOT service it here! */
|
||||||
c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &ms);
|
pfd.fd = com[0];
|
||||||
if (outfd > -1)
|
pfd.events = POLLIN;
|
||||||
break;
|
pfd.revents = 0;
|
||||||
if (!c)
|
/* Wait for pipe activity... if the channel hangs up, we'll catch it on the way out. */
|
||||||
continue;
|
res = ast_poll(&pfd, 1, timeout);
|
||||||
if (!(f = ast_read(c))) {
|
if (res < 0) {
|
||||||
doabort = 1;
|
ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
|
||||||
break;
|
return NULL;
|
||||||
}
|
} else if (!pfd.revents) {
|
||||||
ast_frfree(f);
|
|
||||||
}
|
|
||||||
if (!ms) {
|
|
||||||
ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
|
ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ast_check_hangup(chan)) {
|
||||||
|
doabort = 1;
|
||||||
|
}
|
||||||
|
|
||||||
AST_LIST_LOCK(&dpcache);
|
AST_LIST_LOCK(&dpcache);
|
||||||
dp->waiters[x] = -1;
|
dp->waiters[x] = -1;
|
||||||
close(com[1]);
|
close(com[1]);
|
||||||
close(com[0]);
|
close(com[0]);
|
||||||
if (doabort) {
|
if (doabort) {
|
||||||
/* Don't interpret anything, just abort. Not sure what th epoint
|
/* Don't interpret anything, just abort. */
|
||||||
of undeferring dtmf on a hung up channel is but hey whatever */
|
|
||||||
if (!old && chan)
|
|
||||||
ast_channel_undefer_dtmf(chan);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
|
if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
|
||||||
@@ -14341,8 +14335,6 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Our caller will obtain the rest */
|
/* Our caller will obtain the rest */
|
||||||
if (!old && chan)
|
|
||||||
ast_channel_undefer_dtmf(chan);
|
|
||||||
}
|
}
|
||||||
return dp;
|
return dp;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user