MESSAGE: Flush Message/ast_msg_queue channel alert pipe.

ASTERISK-25083

Change-Id: Id54baa57a8dbca84e29f28bcd2ffc0a5ac12d8b2
This commit is contained in:
Richard Mudgett 2016-12-12 18:38:42 -06:00
parent 31268e0a28
commit 44e72c9d44
3 changed files with 65 additions and 7 deletions

View File

@ -4229,6 +4229,7 @@ typedef enum {
} 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);

View File

@ -1239,14 +1239,9 @@ int ast_channel_alert_write(struct ast_channel *chan)
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,
@ -1255,9 +1250,62 @@ ast_alert_status_t ast_channel_internal_alert_read(struct ast_channel *chan)
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));

View File

@ -775,11 +775,20 @@ static void chan_cleanup(struct ast_channel *chan)
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);
}