diff options
author | Richard Mudgett <rmudgett@digium.com> | 2016-12-12 18:38:42 -0600 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2016-12-14 11:30:58 -0600 |
commit | 75a6afbec53141f26ad41c94c1b3499116b23508 (patch) | |
tree | 568ad5f84e77864a2a029d5617cec859f9aa98dc /main/channel_internal_api.c | |
parent | cd46e86491e3f8946bbe9c97b8a1d7eaf708dda9 (diff) |
MESSAGE: Flush Message/ast_msg_queue channel alert pipe.
ASTERISK-25083
Change-Id: Id54baa57a8dbca84e29f28bcd2ffc0a5ac12d8b2
Diffstat (limited to 'main/channel_internal_api.c')
-rw-r--r-- | main/channel_internal_api.c | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 4bc770d3b..fac4f4bcb 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -1249,14 +1249,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, @@ -1265,9 +1260,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)); |