Skip to content

Commit 169e553

Browse files
InterLinked1kharwell
authored andcommitted
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
1 parent 3e86294 commit 169e553

File tree

1 file changed

+20
-28
lines changed

1 file changed

+20
-28
lines changed

channels/chan_iax2.c

+20-28
Original file line numberDiff line numberDiff line change
@@ -14214,9 +14214,7 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
1421414214
{
1421514215
struct iax2_dpcache *dp = NULL;
1421614216
struct timeval now = ast_tvnow();
14217-
int x, com[2], timeout, old = 0, outfd, doabort, callno;
14218-
struct ast_channel *c = NULL;
14219-
struct ast_frame *f = NULL;
14217+
int x, com[2], timeout, doabort, callno;
1422014218

1422114219
AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) {
1422214220
if (ast_tvcmp(now, dp->expiry) > 0) {
@@ -14263,8 +14261,8 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
1426314261

1426414262
/* By here we must have a dp */
1426514263
if (dp->flags & CACHE_FLAG_PENDING) {
14266-
struct timeval start;
14267-
int ms;
14264+
int res;
14265+
struct pollfd pfd;
1426814266
/* Okay, here it starts to get nasty. We need a pipe now to wait
1426914267
for a reply to come back so long as it's pending */
1427014268
for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
@@ -14285,35 +14283,31 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
1428514283
timeout = iaxdefaulttimeout * 1000;
1428614284
/* Temporarily unlock */
1428714285
AST_LIST_UNLOCK(&dpcache);
14288-
/* Defer any dtmf */
14289-
if (chan)
14290-
old = ast_channel_defer_dtmf(chan);
1429114286
doabort = 0;
14292-
start = ast_tvnow();
14293-
while ((ms = ast_remaining_ms(start, timeout))) {
14294-
c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &ms);
14295-
if (outfd > -1)
14296-
break;
14297-
if (!c)
14298-
continue;
14299-
if (!(f = ast_read(c))) {
14300-
doabort = 1;
14301-
break;
14302-
}
14303-
ast_frfree(f);
14304-
}
14305-
if (!ms) {
14287+
14288+
/* chan is in autoservice here, so do NOT service it here! */
14289+
pfd.fd = com[0];
14290+
pfd.events = POLLIN;
14291+
pfd.revents = 0;
14292+
/* Wait for pipe activity... if the channel hangs up, we'll catch it on the way out. */
14293+
res = ast_poll(&pfd, 1, timeout);
14294+
if (res < 0) {
14295+
ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
14296+
return NULL;
14297+
} else if (!pfd.revents) {
1430614298
ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
1430714299
}
14300+
14301+
if (ast_check_hangup(chan)) {
14302+
doabort = 1;
14303+
}
14304+
1430814305
AST_LIST_LOCK(&dpcache);
1430914306
dp->waiters[x] = -1;
1431014307
close(com[1]);
1431114308
close(com[0]);
1431214309
if (doabort) {
14313-
/* Don't interpret anything, just abort. Not sure what th epoint
14314-
of undeferring dtmf on a hung up channel is but hey whatever */
14315-
if (!old && chan)
14316-
ast_channel_undefer_dtmf(chan);
14310+
/* Don't interpret anything, just abort. */
1431714311
return NULL;
1431814312
}
1431914313
if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
@@ -14336,8 +14330,6 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
1433614330
}
1433714331
}
1433814332
/* Our caller will obtain the rest */
14339-
if (!old && chan)
14340-
ast_channel_undefer_dtmf(chan);
1434114333
}
1434214334
return dp;
1434314335
}

0 commit comments

Comments
 (0)