diff --git a/configure b/configure index dab70385346e6452aab28f3264ca0beb3eefb4d0..89de95ae6bd63cb0cdc1afa75441895b80703b15 100755 --- a/configure +++ b/configure @@ -18009,6 +18009,41 @@ fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have usable eventfd support" >&5 +$as_echo_n "checking if we have usable eventfd support... " >&6; } +if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/eventfd.h> +int +main () +{ +return eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE) == -1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_EVENTFD 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler 'attribute pure' support" >&5 $as_echo_n "checking for compiler 'attribute pure' support... " >&6; } diff --git a/configure.ac b/configure.ac index d8a567fa62202d4e43c0efa739881236793afd7f..3bfb82eea351c0a8238cb9893be6f8973e634e46 100644 --- a/configure.ac +++ b/configure.ac @@ -1125,6 +1125,15 @@ if test "${ac_cv_have_variable_fdset}x" = "0x"; then AC_DEFINE([CONFIGURE_RAN_AS_ROOT], 1, [Some configure tests will unexpectedly fail if configure is run by a non-root user. These may be able to be tested at runtime.])) fi +AC_MSG_CHECKING([if we have usable eventfd support]) +AC_RUN_IFELSE( + [AC_LANG_PROGRAM([#include <sys/eventfd.h>], + [return eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE) == -1;])], + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_EVENTFD], 1, [Define to 1 if your system supports eventfd and the EFD_NONBLOCK and EFD_SEMAPHORE flags.]), + AC_MSG_RESULT(no) +) + AST_GCC_ATTRIBUTE(pure) AST_GCC_ATTRIBUTE(malloc) AST_GCC_ATTRIBUTE(const) diff --git a/include/asterisk/alertpipe.h b/include/asterisk/alertpipe.h new file mode 100644 index 0000000000000000000000000000000000000000..5ff854ce80147190e2271f6c34a522cb5a0a3aab --- /dev/null +++ b/include/asterisk/alertpipe.h @@ -0,0 +1,159 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2017, Sean Bright + * + * Sean Bright <sean.bright@gmail.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +#ifndef ASTERISK_ALERTPIPE_H +#define ASTERISK_ALERTPIPE_H + +#include "asterisk/utils.h" + +typedef enum { + AST_ALERT_READ_SUCCESS = 0, + AST_ALERT_NOT_READABLE, + AST_ALERT_READ_FAIL, + AST_ALERT_READ_FATAL, +} ast_alert_status_t; + +/*! + * \brief Initialize an alert pipe + * \since 13.16.0 + * + * \param p a two-element array to hold the alert pipe's file descriptors + * + * \return non-zero if a failure occurred, zero otherwise. + */ +int ast_alertpipe_init(int alert_pipe[2]); + +/*! + * \brief Close an alert pipe + * \since 13.16.0 + * + * \param p a two-element containing the alert pipe's file descriptors + */ +void ast_alertpipe_close(int alert_pipe[2]); + +/*! + * \brief Read an event from an alert pipe + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \retval AST_ALERT_READ_SUCCESS on success + * \retval AST_ALERT_NOT_READABLE if the alert pipe is not readable + * \retval AST_ALERT_READ_FATAL if the alert pipe's file descriptors are in + * blocking mode, or a read error occurs. + */ +ast_alert_status_t ast_alertpipe_read(int alert_pipe[2]); + +/*! + * \brief Write an event to an alert pipe + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \return see write(2) + */ +ssize_t ast_alertpipe_write(int alert_pipe[2]); + +/*! + * \brief Consume all alerts written to the alert pipe + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \retval AST_ALERT_READ_SUCCESS on success + * \retval AST_ALERT_NOT_READABLE if the alert pipe is not readable + * \retval AST_ALERT_READ_FATAL if the alert pipe's file descriptors are in + * blocking mode, or a read error occurs. + */ +ast_alert_status_t ast_alertpipe_flush(int alert_pipe[2]); + +/*! + * \brief Sets the alert pipe file descriptors to default values + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + */ +AST_INLINE_API( +void ast_alertpipe_clear(int alert_pipe[2]), +{ + alert_pipe[0] = alert_pipe[1] = -1; +} +) + +/*! + * \brief Determine if the alert pipe is readable + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \return non-zero if the alert pipe is readable, zero otherwise. + */ +AST_INLINE_API( +int attribute_pure ast_alertpipe_readable(int alert_pipe[2]), +{ + return alert_pipe[0] > -1; +} +) + +/*! + * \brief Determine if the alert pipe is writable + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \return non-zero if the alert pipe is writable, zero otherwise. + */ +AST_INLINE_API( +int attribute_pure ast_alertpipe_writable(int alert_pipe[2]), +{ + return alert_pipe[1] > -1; +} +) + +/*! + * \brief Get the alert pipe's read file descriptor + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \return -1 if the file descriptor is not initialized, a non-negative value + * otherwise. + */ +AST_INLINE_API( +int attribute_pure ast_alertpipe_readfd(int alert_pipe[2]), +{ + return alert_pipe[0]; +} +) + +/*! + * \brief Swap the file descriptors from two alert pipes + * \since 13.16.0 + * + * \param p1 a two-element array containing an alert pipe's file descriptors + * \param p2 a two-element array containing an alert pipe's file descriptors + */ +AST_INLINE_API( +void ast_alertpipe_swap(int alert_pipe_1[2], int alert_pipe_2[2]), +{ + SWAP(alert_pipe_1[0], alert_pipe_2[0]); + SWAP(alert_pipe_1[1], alert_pipe_2[1]); +} +) + +#endif /* ASTERISK_ALERTPIPE_H */ diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index 5f8a9d37c823e4a8735af671a70871e0e27c4f94..b39386b43495175b6e5d1a802fb633eb88d2f8e7 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -225,6 +225,10 @@ /* Define to 1 if you have the `euidaccess' function. */ #undef HAVE_EUIDACCESS +/* Define to 1 if your system supports eventfd and the EFD_NONBLOCK and + EFD_SEMAPHORE flags. */ +#undef HAVE_EVENTFD + /* Define to 1 if you have the `exp' function. */ #undef HAVE_EXP diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 32c9c7f67f2d6c14fdfee55303c944e5a34733bf..3e04b5d0bb60878e05e9aad517461b41dbd0922c 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -123,6 +123,7 @@ References: #ifndef _ASTERISK_CHANNEL_H #define _ASTERISK_CHANNEL_H +#include "asterisk/alertpipe.h" #include "asterisk/abstract_jb.h" #include "asterisk/astobj2.h" #include "asterisk/poll-compat.h" @@ -4267,12 +4268,6 @@ struct ast_namedgroups *ast_channel_named_pickupgroups(const struct ast_channel void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value); /* Alertpipe accessors--the "internal" functions for channel.c use only */ -typedef enum { - AST_ALERT_READ_SUCCESS = 0, - AST_ALERT_NOT_READABLE, - AST_ALERT_READ_FAIL, - AST_ALERT_READ_FATAL, -} 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); diff --git a/main/alertpipe.c b/main/alertpipe.c new file mode 100644 index 0000000000000000000000000000000000000000..fa6ec7bcce362c0ef51cc57e753dc835ae1fb677 --- /dev/null +++ b/main/alertpipe.c @@ -0,0 +1,166 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2017, Sean Bright + * + * Sean Bright <sean.bright@gmail.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Alert Pipe API + * + * \author Sean Bright + */ + +#include "asterisk.h" + +#include <unistd.h> +#include <fcntl.h> + +#ifdef HAVE_EVENTFD +# include <sys/eventfd.h> +#endif + +#include "asterisk/alertpipe.h" +#include "asterisk/logger.h" + +int ast_alertpipe_init(int alert_pipe[2]) +{ +#ifdef HAVE_EVENTFD + + int fd = eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE); + if (fd > -1) { + alert_pipe[0] = alert_pipe[1] = fd; + return 0; + } + + ast_log(LOG_WARNING, "Failed to create alert pipe with eventfd(), falling back to pipe(): %s\n", + strerror(errno)); + ast_alertpipe_clear(alert_pipe); + +#endif + + if (pipe(alert_pipe)) { + ast_log(LOG_WARNING, "Failed to create alert pipe: %s\n", strerror(errno)); + return -1; + } else { + int flags = fcntl(alert_pipe[0], F_GETFL); + if (fcntl(alert_pipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { + ast_log(LOG_WARNING, "Failed to set non-blocking mode on alert pipe: %s\n", + strerror(errno)); + ast_alertpipe_close(alert_pipe); + return -1; + } + flags = fcntl(alert_pipe[1], F_GETFL); + if (fcntl(alert_pipe[1], F_SETFL, flags | O_NONBLOCK) < 0) { + ast_log(LOG_WARNING, "Failed to set non-blocking mode on alert pipe: %s\n", + strerror(errno)); + ast_alertpipe_close(alert_pipe); + return -1; + } + } + + return 0; +} + +void ast_alertpipe_close(int alert_pipe[2]) +{ +#ifdef HAVE_EVENTFD + + if (alert_pipe[0] == alert_pipe[1]) { + if (alert_pipe[0] > -1) { + close(alert_pipe[0]); + ast_alertpipe_clear(alert_pipe); + } + return; + } + +#endif + + if (alert_pipe[0] > -1) { + close(alert_pipe[0]); + } + if (alert_pipe[1] > -1) { + close(alert_pipe[1]); + } + ast_alertpipe_clear(alert_pipe); +} + +ast_alert_status_t ast_alertpipe_read(int alert_pipe[2]) +{ + uint64_t tmp; + + if (!ast_alertpipe_readable(alert_pipe)) { + return AST_ALERT_NOT_READABLE; + } + + if (read(alert_pipe[0], &tmp, sizeof(tmp)) < 0) { + if (errno != EINTR && errno != EAGAIN) { + ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); + return AST_ALERT_READ_FAIL; + } + } + + return AST_ALERT_READ_SUCCESS; +} + +ssize_t ast_alertpipe_write(int alert_pipe[2]) +{ + uint64_t tmp = 1; + + if (!ast_alertpipe_writable(alert_pipe)) { + errno = EBADF; + return 0; + } + + /* preset errno in case returned size does not match */ + errno = EPIPE; + return write(alert_pipe[1], &tmp, sizeof(tmp)) != sizeof(tmp); +} + +ast_alert_status_t ast_alertpipe_flush(int alert_pipe[2]) +{ + int bytes_read; + uint64_t tmp[16]; + + if (!ast_alertpipe_readable(alert_pipe)) { + return AST_ALERT_NOT_READABLE; + } + + /* Read the alertpipe until it is exhausted. */ + for (;;) { + bytes_read = read(alert_pipe[0], tmp, sizeof(tmp)); + 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; +} diff --git a/main/bridge_channel.c b/main/bridge_channel.c index 7f3c8fe310627cb316cd80204cedc450376bffe1..89222d365e71bd2399c0d696fa7e011afe7cf17f 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -35,6 +35,7 @@ #include <signal.h> #include "asterisk/heap.h" +#include "asterisk/alertpipe.h" #include "asterisk/astobj2.h" #include "asterisk/stringfields.h" #include "asterisk/app.h" @@ -954,7 +955,6 @@ static void bridge_frame_free(struct ast_frame *frame) int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr) { struct ast_frame *dup; - char nudge = 0; if (bridge_channel->suspended /* Also defer DTMF frames. */ @@ -983,7 +983,7 @@ int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, st } AST_LIST_INSERT_TAIL(&bridge_channel->wr_queue, dup, frame_list); - if (write(bridge_channel->alert_pipe[1], &nudge, sizeof(nudge)) != sizeof(nudge)) { + if (ast_alertpipe_write(bridge_channel->alert_pipe)) { ast_log(LOG_ERROR, "We couldn't write alert pipe for %p(%s)... something is VERY wrong\n", bridge_channel, ast_channel_name(bridge_channel->chan)); } @@ -2255,25 +2255,6 @@ static void bridge_channel_handle_control(struct ast_bridge_channel *bridge_chan } } -/*! - * \internal - * \param bridge_channel Channel to read wr_queue alert pipe. - * - * \return Nothing - */ -static void bridge_channel_read_wr_queue_alert(struct ast_bridge_channel *bridge_channel) -{ - char nudge; - - if (read(bridge_channel->alert_pipe[0], &nudge, sizeof(nudge)) < 0) { - if (errno != EINTR && errno != EAGAIN) { - ast_log(LOG_WARNING, "read() failed for alert pipe on %p(%s): %s\n", - bridge_channel, ast_channel_name(bridge_channel->chan), - strerror(errno)); - } - } -} - /*! * \internal * \brief Handle bridge channel write frame to channel. @@ -2296,7 +2277,7 @@ static void bridge_channel_handle_write(struct ast_bridge_channel *bridge_channe /* No frame, flush the alert pipe of excess alerts. */ ast_log(LOG_WARNING, "Weird. No frame from bridge for %s to process?\n", ast_channel_name(bridge_channel->chan)); - bridge_channel_read_wr_queue_alert(bridge_channel); + ast_alertpipe_read(bridge_channel->alert_pipe); ast_bridge_channel_unlock(bridge_channel); return; } @@ -2312,7 +2293,7 @@ static void bridge_channel_handle_write(struct ast_bridge_channel *bridge_channe break; } } - bridge_channel_read_wr_queue_alert(bridge_channel); + ast_alertpipe_read(bridge_channel->alert_pipe); AST_LIST_REMOVE_CURRENT(frame_list); break; } @@ -2879,62 +2860,6 @@ int bridge_channel_internal_allows_optimization(struct ast_bridge_channel *bridg && AST_LIST_EMPTY(&bridge_channel->wr_queue); } -/*! - * \internal - * \brief Close a pipe. - * \since 12.0.0 - * - * \param my_pipe What to close. - * - * \return Nothing - */ -static void pipe_close(int *my_pipe) -{ - if (my_pipe[0] > -1) { - close(my_pipe[0]); - my_pipe[0] = -1; - } - if (my_pipe[1] > -1) { - close(my_pipe[1]); - my_pipe[1] = -1; - } -} - -/*! - * \internal - * \brief Initialize a pipe as non-blocking. - * \since 12.0.0 - * - * \param my_pipe What to initialize. - * - * \retval 0 on success. - * \retval -1 on error. - */ -static int pipe_init_nonblock(int *my_pipe) -{ - int flags; - - my_pipe[0] = -1; - my_pipe[1] = -1; - if (pipe(my_pipe)) { - ast_log(LOG_WARNING, "Can't create pipe! Try increasing max file descriptors with ulimit -n\n"); - return -1; - } - flags = fcntl(my_pipe[0], F_GETFL); - if (fcntl(my_pipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "Unable to set read pipe nonblocking! (%d: %s)\n", - errno, strerror(errno)); - return -1; - } - flags = fcntl(my_pipe[1], F_GETFL); - if (fcntl(my_pipe[1], F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "Unable to set write pipe nonblocking! (%d: %s)\n", - errno, strerror(errno)); - return -1; - } - return 0; -} - /* Destroy elements of the bridge channel structure and the bridge channel structure itself */ static void bridge_channel_destroy(void *obj) { @@ -2954,7 +2879,7 @@ static void bridge_channel_destroy(void *obj) while ((fr = AST_LIST_REMOVE_HEAD(&bridge_channel->wr_queue, frame_list))) { bridge_frame_free(fr); } - pipe_close(bridge_channel->alert_pipe); + ast_alertpipe_close(bridge_channel->alert_pipe); ast_cond_destroy(&bridge_channel->cond); @@ -2971,7 +2896,7 @@ struct ast_bridge_channel *bridge_channel_internal_alloc(struct ast_bridge *brid return NULL; } ast_cond_init(&bridge_channel->cond, NULL); - if (pipe_init_nonblock(bridge_channel->alert_pipe)) { + if (ast_alertpipe_init(bridge_channel->alert_pipe)) { ao2_ref(bridge_channel, -1); return NULL; } diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index b3c0a480538ce66f038d361d4c6b2a66537c3a56..d838ea80cfb6d3d1cf11a9802f745b96462cf492 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -36,6 +36,7 @@ #include <unistd.h> #include <fcntl.h> +#include "asterisk/alertpipe.h" #include "asterisk/paths.h" #include "asterisk/channel.h" #include "asterisk/channel_internal.h" @@ -1265,152 +1266,52 @@ void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_nam /* Alertpipe functions */ int ast_channel_alert_write(struct ast_channel *chan) { - char blah = 0x7F; - - if (!ast_channel_alert_writable(chan)) { - errno = EBADF; - return 0; - } - /* preset errno in case returned size does not match */ - errno = EPIPE; - return write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah); -} - -static int channel_internal_alert_check_nonblock(struct ast_channel *chan) -{ - int flags; - - flags = fcntl(chan->alertpipe[0], F_GETFL); - /* For some odd reason, the alertpipe occasionally loses nonblocking status, - * which immediately causes a deadlock scenario. Detect and prevent this. */ - if ((flags & O_NONBLOCK) == 0) { - 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 -1; - } - } - return 0; + return ast_alertpipe_write(chan->alertpipe); } 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; + return ast_alertpipe_flush(chan->alertpipe); } 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)); - return AST_ALERT_READ_FAIL; - } - } - - return AST_ALERT_READ_SUCCESS; + return ast_alertpipe_read(chan->alertpipe); } int ast_channel_alert_writable(struct ast_channel *chan) { - return chan->alertpipe[1] > -1; + return ast_alertpipe_writable(chan->alertpipe); } int ast_channel_internal_alert_readable(struct ast_channel *chan) { - return chan->alertpipe[0] > -1; + return ast_alertpipe_readable(chan->alertpipe); } void ast_channel_internal_alertpipe_clear(struct ast_channel *chan) { - chan->alertpipe[0] = chan->alertpipe[1] = -1; + ast_alertpipe_clear(chan->alertpipe); } void ast_channel_internal_alertpipe_close(struct ast_channel *chan) { - if (ast_channel_internal_alert_readable(chan)) { - close(chan->alertpipe[0]); - chan->alertpipe[0] = -1; - } - if (ast_channel_alert_writable(chan)) { - close(chan->alertpipe[1]); - chan->alertpipe[1] = -1; - } + ast_alertpipe_close(chan->alertpipe); } int ast_channel_internal_alertpipe_init(struct ast_channel *chan) { - if (pipe(chan->alertpipe)) { - ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n\n"); - return -1; - } else { - int flags = fcntl(chan->alertpipe[0], F_GETFL); - if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); - return -1; - } - flags = fcntl(chan->alertpipe[1], F_GETFL); - if (fcntl(chan->alertpipe[1], F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); - return -1; - } - } - return 0; + return ast_alertpipe_init(chan->alertpipe); } int ast_channel_internal_alert_readfd(struct ast_channel *chan) { - return chan->alertpipe[0]; + return ast_alertpipe_readfd(chan->alertpipe); } void ast_channel_internal_alertpipe_swap(struct ast_channel *chan1, struct ast_channel *chan2) { - int i; - for (i = 0; i < ARRAY_LEN(chan1->alertpipe); i++) { - SWAP(chan1->alertpipe[i], chan2->alertpipe[i]); - } + ast_alertpipe_swap(chan1->alertpipe, chan2->alertpipe); } /* file descriptor array accessors */ diff --git a/main/utils.c b/main/utils.c index 2033664b84de94774785432991b3e6623ac88c37..c254db52060e6b80989a0d1481a99cab91bc947e 100644 --- a/main/utils.c +++ b/main/utils.c @@ -67,6 +67,9 @@ #define AST_API_MODULE #include "asterisk/config.h" +#define AST_API_MODULE +#include "asterisk/alertpipe.h" + static char base64[64]; static char b2a[256];