[Asterisk-code-review] MESSAGE: Flush Message/ast msg queue channel alert pipe. (asterisk[14])

Richard Mudgett asteriskteam at digium.com
Wed Dec 14 11:41:11 CST 2016


Richard Mudgett has uploaded a new change for review. ( https://gerrit.asterisk.org/4623 )

Change subject: MESSAGE: Flush Message/ast_msg_queue channel alert pipe.
......................................................................

MESSAGE: Flush Message/ast_msg_queue channel alert pipe.

ASTERISK-25083

Change-Id: Id54baa57a8dbca84e29f28bcd2ffc0a5ac12d8b2
---
M include/asterisk/channel.h
M main/channel_internal_api.c
M main/message.c
3 files changed, 65 insertions(+), 7 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/23/4623/1

diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 1637371..2f473ab 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -4219,6 +4219,7 @@
 } ast_alert_status_t;
 int ast_channel_alert_write(struct ast_channel *chan);
 int ast_channel_alert_writable(struct ast_channel *chan);
+ast_alert_status_t ast_channel_internal_alert_flush(struct ast_channel *chan);
 ast_alert_status_t ast_channel_internal_alert_read(struct ast_channel *chan);
 int ast_channel_internal_alert_readable(struct ast_channel *chan);
 void ast_channel_internal_alertpipe_clear(struct ast_channel *chan);
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index a30c605..9f86938 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -1241,14 +1241,9 @@
 	return write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah);
 }
 
-ast_alert_status_t ast_channel_internal_alert_read(struct ast_channel *chan)
+static int channel_internal_alert_check_nonblock(struct ast_channel *chan)
 {
 	int flags;
-	char blah;
-
-	if (!ast_channel_internal_alert_readable(chan)) {
-		return AST_ALERT_NOT_READABLE;
-	}
 
 	flags = fcntl(chan->alertpipe[0], F_GETFL);
 	/* For some odd reason, the alertpipe occasionally loses nonblocking status,
@@ -1257,9 +1252,62 @@
 		ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", ast_channel_name(chan));
 		if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
 			ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
-			return AST_ALERT_READ_FATAL;
+			return -1;
 		}
 	}
+	return 0;
+}
+
+ast_alert_status_t ast_channel_internal_alert_flush(struct ast_channel *chan)
+{
+	int bytes_read;
+	char blah[100];
+
+	if (!ast_channel_internal_alert_readable(chan)) {
+		return AST_ALERT_NOT_READABLE;
+	}
+	if (channel_internal_alert_check_nonblock(chan)) {
+		return AST_ALERT_READ_FATAL;
+	}
+
+	/* Read the alertpipe until it is exhausted. */
+	for (;;) {
+		bytes_read = read(chan->alertpipe[0], blah, sizeof(blah));
+		if (bytes_read < 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				/*
+				 * Would block so nothing left to read.
+				 * This is the normal loop exit.
+				 */
+				break;
+			}
+			ast_log(LOG_WARNING, "read() failed flushing alertpipe: %s\n",
+				strerror(errno));
+			return AST_ALERT_READ_FAIL;
+		}
+		if (!bytes_read) {
+			/* Read nothing so we are done */
+			break;
+		}
+	}
+
+	return AST_ALERT_READ_SUCCESS;
+}
+
+ast_alert_status_t ast_channel_internal_alert_read(struct ast_channel *chan)
+{
+	char blah;
+
+	if (!ast_channel_internal_alert_readable(chan)) {
+		return AST_ALERT_NOT_READABLE;
+	}
+	if (channel_internal_alert_check_nonblock(chan)) {
+		return AST_ALERT_READ_FATAL;
+	}
+
 	if (read(chan->alertpipe[0], &blah, sizeof(blah)) < 0) {
 		if (errno != EINTR && errno != EAGAIN) {
 			ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
diff --git a/main/message.c b/main/message.c
index 0fc67ec..7a6d019 100644
--- a/main/message.c
+++ b/main/message.c
@@ -777,11 +777,20 @@
 	if (msg_ds) {
 		ast_channel_datastore_add(chan, msg_ds);
 	}
+
 	/*
 	 * Clear softhangup flags.
 	 */
 	ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_ALL);
 
+	/*
+	 * Flush the alert pipe in case we miscounted somewhere when
+	 * messing with frames on the read queue, we had to flush the
+	 * read queue above, or we had an "Exceptionally long queue
+	 * length" event.
+	 */
+	ast_channel_internal_alert_flush(chan);
+
 	ast_channel_unlock(chan);
 }
 

-- 
To view, visit https://gerrit.asterisk.org/4623
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id54baa57a8dbca84e29f28bcd2ffc0a5ac12d8b2
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 14
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>



More information about the asterisk-code-review mailing list