[Asterisk-code-review] chan_iax2: Prevent deadlock due to duplicate autoservice. (asterisk[19])

N A asteriskteam at digium.com
Thu Jun 2 12:22:06 CDT 2022


N A has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/18599 )


Change subject: chan_iax2: Prevent deadlock due to duplicate autoservice.
......................................................................

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
---
M channels/chan_iax2.c
1 file changed, 20 insertions(+), 28 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/99/18599/1

diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 6d76dc5..210c344 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -14214,9 +14214,7 @@
 {
 	struct iax2_dpcache *dp = NULL;
 	struct timeval now = ast_tvnow();
-	int x, com[2], timeout, old = 0, outfd, doabort, callno;
-	struct ast_channel *c = NULL;
-	struct ast_frame *f = NULL;
+	int x, com[2], timeout, doabort, callno;
 
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) {
 		if (ast_tvcmp(now, dp->expiry) > 0) {
@@ -14263,8 +14261,8 @@
 
 	/* By here we must have a dp */
 	if (dp->flags & CACHE_FLAG_PENDING) {
-		struct timeval start;
-		int ms;
+		int res;
+		struct pollfd pfd;
 		/* 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 (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
@@ -14285,35 +14283,31 @@
 		timeout = iaxdefaulttimeout * 1000;
 		/* Temporarily unlock */
 		AST_LIST_UNLOCK(&dpcache);
-		/* Defer any dtmf */
-		if (chan)
-			old = ast_channel_defer_dtmf(chan);
 		doabort = 0;
-		start = ast_tvnow();
-		while ((ms = ast_remaining_ms(start, timeout))) {
-			c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &ms);
-			if (outfd > -1)
-				break;
-			if (!c)
-				continue;
-			if (!(f = ast_read(c))) {
-				doabort = 1;
-				break;
-			}
-			ast_frfree(f);
-		}
-		if (!ms) {
+
+		/* chan is in autoservice here, so do NOT service it here! */
+		pfd.fd = com[0];
+		pfd.events = POLLIN;
+		pfd.revents = 0;
+		/* Wait for pipe activity... if the channel hangs up, we'll catch it on the way out. */
+		res = ast_poll(&pfd, 1, timeout);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
+			return NULL;
+		} else if (!pfd.revents) {
 			ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
 		}
+
+		if (ast_check_hangup(chan)) {
+			doabort = 1;
+		}
+
 		AST_LIST_LOCK(&dpcache);
 		dp->waiters[x] = -1;
 		close(com[1]);
 		close(com[0]);
 		if (doabort) {
-			/* Don't interpret anything, just abort.  Not sure what th epoint
-			  of undeferring dtmf on a hung up channel is but hey whatever */
-			if (!old && chan)
-				ast_channel_undefer_dtmf(chan);
+			/* Don't interpret anything, just abort. */
 			return NULL;
 		}
 		if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
@@ -14336,8 +14330,6 @@
 			}
 		}
 		/* Our caller will obtain the rest */
-		if (!old && chan)
-			ast_channel_undefer_dtmf(chan);
 	}
 	return dp;
 }

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/18599
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 19
Gerrit-Change-Id: Ie92f206d32f9a36924af734ddde652b21106af22
Gerrit-Change-Number: 18599
Gerrit-PatchSet: 1
Gerrit-Owner: N A <mail at interlinked.x10host.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220602/bcf8a5c0/attachment.html>


More information about the asterisk-code-review mailing list