[asterisk-commits] kpfleming: branch kpfleming/eventfd r340162 - in /team/kpfleming/eventfd: ./ ...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Oct 10 11:51:44 CDT 2011
Author: kpfleming
Date: Mon Oct 10 11:51:38 2011
New Revision: 340162
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=340162
Log:
Create a branch to test out usage of eventfd() instead of pipes for alerting
channel threads.
Added:
team/kpfleming/eventfd/
- copied from r340161, trunk/
Modified:
team/kpfleming/eventfd/channels/console_video.c
team/kpfleming/eventfd/configure
team/kpfleming/eventfd/configure.ac
team/kpfleming/eventfd/include/asterisk/autoconfig.h.in
team/kpfleming/eventfd/include/asterisk/channel.h
team/kpfleming/eventfd/main/channel.c
Modified: team/kpfleming/eventfd/channels/console_video.c
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/channels/console_video.c?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/channels/console_video.c (original)
+++ team/kpfleming/eventfd/channels/console_video.c Mon Oct 10 11:51:38 2011
@@ -965,36 +965,14 @@
chan = env->owner;
if (chan == NULL) {
/* drop the chain of frames, nobody uses them */
- while (f) {
- struct ast_frame *g = AST_LIST_NEXT(f, frame_list);
- ast_frfree(f);
- f = g;
- }
+ ast_frfree(f);
continue;
}
- fd = chan->alertpipe[1];
- ast_channel_lock(chan);
-
- /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */
- if (chan->readq.first == NULL) {
- chan->readq.first = f;
- } else {
- chan->readq.last->frame_list.next = f;
- }
- chan->readq.last = p;
- /*
- * more or less same as ast_queue_frame, but extra
- * write on the alertpipe to signal frames.
- */
- if (fd > -1) {
- int blah = 1, l = sizeof(blah);
- for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
- if (write(fd, &blah, l) != l)
- ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
- chan->name, f->frametype, f->subclass, strerror(errno));
- }
- }
- ast_channel_unlock(chan);
+
+ /* Queue the chain of frames, and poke the alertpipe/eventfd if
+ necessary.
+ */
+ ast_queue_frame(chan, f);
}
/* thread terminating, here could call the uninit */
/* uninitialize the local and remote video environments */
Modified: team/kpfleming/eventfd/configure.ac
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/configure.ac?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/configure.ac (original)
+++ team/kpfleming/eventfd/configure.ac Mon Oct 10 11:51:38 2011
@@ -210,7 +210,7 @@
)
# cross-compile checks
-if test "${cross_compiling}" = "yes";
+if test "${cross_compiling}" = "yes";
then
AC_CHECK_TOOL(CC, gcc, :)
AC_CHECK_TOOL(CXX, g++, :)
@@ -323,7 +323,7 @@
AC_CHECK_PROGS([MD5], [md5 md5sum gmd5sum digest])
if test "${MD5}" = "digest" ; then
- MD5="${MD5} -a md5"
+ MD5="${MD5} -a md5"
fi
ACX_PTHREAD
@@ -334,7 +334,7 @@
[AS_HELP_STRING([--enable-dev-mode],
[Turn on developer mode])],
[case "${enableval}" in
- y|ye|yes) AST_DEVMODE=yes ;;
+ y|yes) AST_DEVMODE=yes ;;
n|no) AST_DEVMODE=no ;;
noisy)
AST_DEVMODE=yes
@@ -350,7 +350,7 @@
[AS_HELP_STRING([--enable-coverage],
[Turn on code coverage tracking (for gcov)])],
[case "${enableval}" in
- y|ye|yes) AST_CODE_COVERAGE=yes ;;
+ y|yes) AST_CODE_COVERAGE=yes ;;
n|no) AST_CODE_COVERAGE=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-coverage) ;;
esac])
@@ -500,7 +500,7 @@
[AS_HELP_STRING([--disable-xmldoc],
[Explicity disable XML documentation])],
[case "${enableval}" in
- y|ye|yes) disable_xmldoc=no ;;
+ y|yes) disable_xmldoc=no ;;
n|no) disable_xmldoc=yes ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-xmldoc) ;;
esac], [disable_xmldoc=no])
@@ -572,6 +572,17 @@
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob htonll ioperm inet_ntoa isascii memchr memmove memset mkdir mkdtemp munmap ntohll newlocale ppoll putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv utime vasprintf getpeereid sysctl swapctl])
+AC_ARG_ENABLE([eventfd],
+ [AS_HELP_STRING([--disable-eventfd],
+ [Disable usage of eventfd()])],
+ [case "${enableval}" in
+ y|yes) AC_CHECK_FUNCS([eventfd]) ;;
+ n|no) ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --disable-eventfd) ;;
+ esac],
+ AC_CHECK_FUNCS([eventfd])
+)
+
# NOTE: we use AC_CHECK_LIB to get -lm into the arguments for later checks,
# so that AC_CHECK_FUNCS can detect functions in that library.
AC_CHECK_LIB([m], [sqrt])
@@ -621,7 +632,7 @@
LDFLAGS=${old_LDFLAGS}
rm -f conftest.dynamics
-AC_CHECK_HEADER([sys/poll.h],
+AC_CHECK_HEADER([sys/poll.h],
[HAS_POLL=1]
AC_DEFINE([HAVE_SYS_POLL_H], 1, [Define to 1 if your system has working sys/poll.h]),
)
@@ -630,7 +641,7 @@
[AS_HELP_STRING([--enable-internal-poll],
[Use Asterisk's poll implementation])],
[case "${enableval}" in
- y|ye|yes) HAS_POLL="";;
+ y|yes) HAS_POLL="";;
n|no) HAS_POLL="${HAS_POLL}" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-internal-poll) ;;
esac])
@@ -1453,7 +1464,7 @@
fi
fi
fi
- fi
+ fi
if test "${IMAP_TK_DIR}" = "system"; then
#We will enter here if user specified "system" or if any of above checks failed
AC_MSG_CHECKING([for system c-client library...])
@@ -1711,7 +1722,7 @@
AC_DEFINE([HAVE_IMAP_TK2006], 1, [Define if your system has the UW IMAP Toolkit c-client library version 2006 or greater.])
fi
else
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT(no)
fi
CPPFLAGS="${saved_cppflags}"
LIBS="${saved_libs}"
@@ -1782,7 +1793,7 @@
AST_EXT_LIB_CHECK([OSS], [ossaudio], [oss_ioctl_mixer], [soundcard.h])
PG_CONFIG=No
-if test "${USE_PGSQL}" != "no"; then
+if test "${USE_PGSQL}" != "no"; then
if test "x${PGSQL_DIR}" != "x"; then
AC_PATH_TOOL([PG_CONFIG], [pg_config], No, [${PGSQL_DIR}/bin])
if test x"${PG_CONFIG}" = xNo; then
@@ -1808,7 +1819,7 @@
AC_MSG_NOTICE([*** including --without-postgres])
exit 1
fi
- else
+ else
AC_CHECK_LIB([pq], [PQescapeStringConn], AC_DEFINE_UNQUOTED([HAVE_PGSQL], 1,
[Define to indicate the PostgreSQL library]), [], -L${PGSQL_libdir} -lz)
@@ -1901,7 +1912,7 @@
fi
AST_CHECK_PWLIB()
AST_CHECK_PWLIB_VERSION([PWLib], [PWLIB], [ptbuildopts.h], [1], [9], [2], [P[[WT]]LIB_VERSION])
-
+
if test "${HAS_PWLIB:-unset}" != "unset"; then
AST_CHECK_PWLIB_PLATFORM()
@@ -1931,7 +1942,7 @@
[${PWLIB_INCLUDE}], [${PWLIB_LIB}])
fi
-AST_EXT_LIB_CHECK([LUA], [lua5.1], [luaL_newstate], [lua5.1/lua.h], [-lm])
+AST_EXT_LIB_CHECK([LUA], [lua5.1], [luaL_newstate], [lua5.1/lua.h], [-lm])
if test "x${PBX_LUA}" = "x1" ; then
if test x"${LUA_DIR}" = x; then
LUA_INCLUDE="${LUA_INCLUDE} -I/usr/include/lua5.1"
@@ -1939,9 +1950,9 @@
LUA_INCLUDE="${LUA_INCLUDE} -I${LUA_DIR}/lua5.1"
fi
fi
-
+
# Some distributions (like SuSE) remove the 5.1 suffix.
-AST_EXT_LIB_CHECK([LUA], [lua], [luaL_register], [lua.h], [-lm])
+AST_EXT_LIB_CHECK([LUA], [lua], [luaL_register], [lua.h], [-lm])
AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h])
@@ -2107,11 +2118,11 @@
[#include <vpbapi.h>],
[int q = vpb_open(0,0);])
],
- [ AC_MSG_RESULT(yes)
- ac_cv_lib_vpb_vpb_open="yes"
+ [ AC_MSG_RESULT(yes)
+ ac_cv_lib_vpb_vpb_open="yes"
],
- [ AC_MSG_RESULT(no)
- ac_cv_lib_vpb_vpb_open="no"
+ [ AC_MSG_RESULT(no)
+ ac_cv_lib_vpb_vpb_open="no"
]
)
LIBS="${saved_libs}"
@@ -2293,8 +2304,8 @@
AC_MSG_NOTICE(Package configured for: )
AC_MSG_NOTICE( OS type : $host_os)
AC_MSG_NOTICE( Host CPU : $host_cpu)
-AC_MSG_NOTICE( build-cpu:vendor:os: $build_cpu : $build_vendor : $build_os :)
-AC_MSG_NOTICE( host-cpu:vendor:os: $host_cpu : $host_vendor : $host_os :)
+AC_MSG_NOTICE( build-cpu:vendor:os: $build_cpu : $build_vendor : $build_os :)
+AC_MSG_NOTICE( host-cpu:vendor:os: $host_cpu : $host_vendor : $host_os :)
if test "${cross_compiling}" = "yes"; then
AC_MSG_NOTICE( Cross Compilation = YES)
fi
Modified: team/kpfleming/eventfd/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/include/asterisk/autoconfig.h.in?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/include/asterisk/autoconfig.h.in (original)
+++ team/kpfleming/eventfd/include/asterisk/autoconfig.h.in Mon Oct 10 11:51:38 2011
@@ -192,6 +192,9 @@
/* Define to 1 if you have the `euidaccess' function. */
#undef HAVE_EUIDACCESS
+/* Define to 1 if you have the `eventfd' function. */
+#undef HAVE_EVENTFD
+
/* Define to 1 if you have the `exp' function. */
#undef HAVE_EXP
@@ -836,16 +839,16 @@
/* Define to 1 if you have the `strtoq' function. */
#undef HAVE_STRTOQ
-/* Define to 1 if `ifr_ifru.ifru_hwaddr' is member of `struct ifreq'. */
+/* Define to 1 if `ifr_ifru.ifru_hwaddr' is a member of `struct ifreq'. */
#undef HAVE_STRUCT_IFREQ_IFR_IFRU_IFRU_HWADDR
-/* Define to 1 if `st_blksize' is member of `struct stat'. */
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
-/* Define to 1 if `cr_uid' is member of `struct ucred'. */
+/* Define to 1 if `cr_uid' is a member of `struct ucred'. */
#undef HAVE_STRUCT_UCRED_CR_UID
-/* Define to 1 if `uid' is member of `struct ucred'. */
+/* Define to 1 if `uid' is a member of `struct ucred'. */
#undef HAVE_STRUCT_UCRED_UID
/* Define to 1 if you have the mISDN Supplemental Services library. */
@@ -1122,6 +1125,9 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
Modified: team/kpfleming/eventfd/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/include/asterisk/channel.h?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/include/asterisk/channel.h (original)
+++ team/kpfleming/eventfd/include/asterisk/channel.h Mon Oct 10 11:51:38 2011
@@ -159,7 +159,7 @@
* We have AST_MAX_FDS file descriptors in a channel.
* Some of them have a fixed use:
*/
-#define AST_ALERT_FD (AST_MAX_FDS-1) /*!< used for alertpipe */
+#define AST_ALERT_FD (AST_MAX_FDS-1) /*!< used for alertpipe or eventfd */
#define AST_TIMING_FD (AST_MAX_FDS-2) /*!< used for timingfd */
#define AST_AGENT_FD (AST_MAX_FDS-3) /*!< used by agents for pass through */
#define AST_GENERATOR_FD (AST_MAX_FDS-4) /*!< used by generator */
@@ -832,7 +832,7 @@
int fdno; /*!< Which fd had an event detected on */
int streamid; /*!< For streaming playback, the schedule ID */
int vstreamid; /*!< For streaming video playback, the schedule ID */
- struct ast_format oldwriteformat; /*!< Original writer format */
+ struct ast_format oldwriteformat; /*!< Original writer format */
int timingfd; /*!< Timing fd */
enum ast_channel_state _state; /*!< State of line -- Don't write directly, use ast_setstate() */
int rings; /*!< Number of rings so far */
@@ -846,12 +846,12 @@
* the counter is only in the remaining bits */
int hangupcause; /*!< Why is the channel hanged up. See causes.h */
unsigned int flags; /*!< channel flags of AST_FLAG_ type */
- int alertpipe[2];
- struct ast_format_cap *nativeformats; /*!< Kinds of data this channel can natively handle */
- struct ast_format readformat; /*!< Requested read format (after translation) */
- struct ast_format writeformat; /*!< Requested write format (after translation) */
- struct ast_format rawreadformat; /*!< Raw read format (before translation) */
- struct ast_format rawwriteformat; /*!< Raw write format (before translation) */
+ int alertpipe[2]; /*!< not used if HAVE_EVENTFD */
+ struct ast_format_cap *nativeformats; /*!< Kinds of data this channel can natively handle */
+ struct ast_format readformat; /*!< Requested read format (after translation) */
+ struct ast_format writeformat; /*!< Requested write format (after translation) */
+ struct ast_format rawreadformat; /*!< Raw read format (before translation) */
+ struct ast_format rawwriteformat; /*!< Raw write format (before translation) */
unsigned int emulate_dtmf_duration; /*!< Number of ms left to emulate DTMF for */
#ifdef HAVE_EPOLL
int epfd;
Modified: team/kpfleming/eventfd/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/eventfd/main/channel.c?view=diff&rev=340162&r1=340161&r2=340162
==============================================================================
--- team/kpfleming/eventfd/main/channel.c (original)
+++ team/kpfleming/eventfd/main/channel.c Mon Oct 10 11:51:38 2011
@@ -32,6 +32,14 @@
#include <sys/time.h>
#include <signal.h>
#include <math.h>
+
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+#ifdef HAVE_EVENTFD
+#include <sys/eventfd.h>
+#endif
#include "asterisk/paths.h" /* use ast_config_AST_SYSTEM_NAME */
@@ -68,10 +76,6 @@
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
#include "asterisk/data.h"
-
-#ifdef HAVE_EPOLL
-#include <sys/epoll.h>
-#endif
#if defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED)
#if defined(HAVE_PRI)
@@ -1124,7 +1128,6 @@
{
struct ast_channel *tmp;
int x;
- int flags;
struct varshead *headp;
char *tech = "", *tech2 = NULL;
@@ -1158,9 +1161,11 @@
* the destructor can know not to close them.
*/
tmp->timingfd = -1;
+#ifndef HAVE_EVENTFD
for (x = 0; x < ARRAY_LEN(tmp->alertpipe); ++x) {
tmp->alertpipe[x] = -1;
}
+#endif
for (x = 0; x < ARRAY_LEN(tmp->fds); ++x) {
tmp->fds[x] = -1;
}
@@ -1200,23 +1205,43 @@
tmp->timingfd = ast_timer_fd(tmp->timer);
}
+#ifndef HAVE_EVENTFD
if (needqueue) {
+ int flags;
+
if (pipe(tmp->alertpipe)) {
- ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n\n");
+ ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n: %s\n", strerror(errno));
return ast_channel_unref(tmp);
- } else {
- flags = fcntl(tmp->alertpipe[0], F_GETFL);
- if (fcntl(tmp->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 ast_channel_unref(tmp);
- }
- flags = fcntl(tmp->alertpipe[1], F_GETFL);
- if (fcntl(tmp->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 ast_channel_unref(tmp);
- }
- }
- }
+ }
+
+ flags = fcntl(tmp->alertpipe[0], F_GETFL);
+ if (fcntl(tmp->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 ast_channel_unref(tmp);
+ }
+
+ flags = fcntl(tmp->alertpipe[1], F_GETFL);
+ if (fcntl(tmp->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 ast_channel_unref(tmp);
+ }
+
+ /* Always watch the alertpipe */
+ ast_channel_set_fd(tmp, AST_ALERT_FD, tmp->alertpipe[0]);
+ }
+#else
+ if (needqueue) {
+ int efd;
+
+ if ((efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE)) == -1) {
+ ast_log(LOG_WARNING, "Channel allocation failed: Can't create eventfd! Try increasing max file descriptors with ulimit -n: %s\n", strerror(errno));
+ return ast_channel_unref(tmp);
+ }
+
+ /* Always watch the eventfd */
+ ast_channel_set_fd(tmp, AST_ALERT_FD, efd);
+ }
+#endif
/*
* This is the last place the channel constructor can fail.
@@ -1229,8 +1254,6 @@
return ast_channel_unref(tmp);
}
- /* Always watch the alertpipe */
- ast_channel_set_fd(tmp, AST_ALERT_FD, tmp->alertpipe[0]);
/* And timing pipe */
ast_channel_set_fd(tmp, AST_TIMING_FD, tmp->timingfd);
@@ -1414,7 +1437,6 @@
{
struct ast_frame *f;
struct ast_frame *cur;
- int blah = 1;
unsigned int new_frames = 0;
unsigned int new_voice_frames = 0;
unsigned int queued_frames = 0;
@@ -1512,11 +1534,23 @@
AST_LIST_APPEND_LIST(&chan->readq, &frames, frame_list);
}
- if (chan->alertpipe[1] > -1) {
- if (write(chan->alertpipe[1], &blah, new_frames * sizeof(blah)) != (new_frames * sizeof(blah))) {
+ if (chan->fds[AST_ALERT_FD] > -1) {
+#ifndef HAVE_EVENTFD
+ int blah[new_frames];
+
+ memset(blah, 1, sizeof(blah));
+ if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) {
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s (qlen = %d): %s!\n",
chan->name, queued_frames, strerror(errno));
}
+#else
+ uint64_t blah = new_frames;
+
+ if (write(chan->fds[AST_ALERT_FD], &blah, sizeof(blah)) != sizeof(blah)) {
+ ast_log(LOG_WARNING, "Unable to write to eventfd on %s (qlen = %d): %s!\n",
+ chan->name, queued_frames, strerror(errno));
+ }
+#endif
} else if (chan->timingfd > -1) {
ast_timer_enable_continuous(chan->timer);
} else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
@@ -2451,11 +2485,17 @@
ast_party_connected_line_free(&chan->connected);
ast_party_redirecting_free(&chan->redirecting);
+#ifndef HAVE_EVENTFD
/* Close pipes if appropriate */
if ((fd = chan->alertpipe[0]) > -1)
close(fd);
if ((fd = chan->alertpipe[1]) > -1)
close(fd);
+#else
+ if ((fd = chan->fds[AST_ALERT_FD]) > -1) {
+ close(fd);
+ }
+#endif
if (chan->timer) {
ast_timer_close(chan->timer);
}
@@ -3764,7 +3804,6 @@
static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
{
struct ast_frame *f = NULL; /* the return value */
- int blah;
int prestate;
int cause = 0;
@@ -3826,78 +3865,8 @@
prestate = chan->_state;
- /* Read and ignore anything on the alertpipe, but read only
- one sizeof(blah) per frame that we send from it */
- if (chan->alertpipe[0] > -1) {
- int 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", chan->name);
- 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));
- f = &ast_null_frame;
- goto done;
- }
- }
- if (read(chan->alertpipe[0], &blah, sizeof(blah)) < 0) {
- if (errno != EINTR && errno != EAGAIN)
- ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
- }
- }
-
- if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD) {
- enum ast_timer_event res;
-
- ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-
- res = ast_timer_get_event(chan->timer);
-
- switch (res) {
- case AST_TIMING_EVENT_EXPIRED:
- ast_timer_ack(chan->timer, 1);
-
- if (chan->timingfunc) {
- /* save a copy of func/data before unlocking the channel */
- int (*func)(const void *) = chan->timingfunc;
- void *data = chan->timingdata;
- chan->fdno = -1;
- ast_channel_unlock(chan);
- func(data);
- } else {
- ast_timer_set_rate(chan->timer, 0);
- chan->fdno = -1;
- ast_channel_unlock(chan);
- }
-
- /* cannot 'goto done' because the channel is already unlocked */
- return &ast_null_frame;
-
- case AST_TIMING_EVENT_CONTINUOUS:
- if (AST_LIST_EMPTY(&chan->readq) ||
- !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) {
- ast_timer_disable_continuous(chan->timer);
- }
- break;
- }
-
- } else if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) {
- /* if the AST_GENERATOR_FD is set, call the generator with args
- * set to -1 so it can do whatever it needs to.
- */
- void *tmp = chan->generatordata;
- chan->generatordata = NULL; /* reset to let ast_write get through */
- chan->generator->generate(chan, tmp, -1, -1);
- chan->generatordata = tmp;
- f = &ast_null_frame;
- chan->fdno = -1;
- goto done;
- } else if (chan->fds[AST_JITTERBUFFER_FD] > -1 && chan->fdno == AST_JITTERBUFFER_FD) {
- ast_clear_flag(chan, AST_FLAG_EXCEPTION);
- }
-
- /* Check for pending read queue */
- if (!AST_LIST_EMPTY(&chan->readq)) {
+ if ((chan->fds[AST_ALERT_FD] > -1) &&
+ (chan->fdno == AST_ALERT_FD)) {
int skip_dtmf = should_skip_dtmf(chan);
AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->readq, f, frame_list) {
@@ -3905,7 +3874,7 @@
* there are cases where we want to leave DTMF frames on the queue until
* some later time. */
- if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
+ if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
continue;
}
@@ -3913,18 +3882,40 @@
break;
}
AST_LIST_TRAVERSE_SAFE_END;
-
+
+#ifndef HAVE_EVENTFD
+ if (f) {
+ int blah;
+ int 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", chan->name);
+ 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));
+ f = &ast_null_frame;
+ goto done;
+ }
+ }
+ if (read(chan->alertpipe[0], &blah, sizeof(blah)) != sizeof(blah)) {
+ if (errno != EINTR && errno != EAGAIN) {
+ ast_log(LOG_WARNING, "read() on alertpipe failed: %s\n", strerror(errno));
+ }
+ }
+ }
+#else
+ if (f) {
+ uint64_t blah;
+ if (read(chan->fds[AST_ALERT_FD], &blah, sizeof(blah)) != sizeof(blah)) {
+ if (errno != EINTR && errno != EAGAIN) {
+ ast_log(LOG_WARNING, "read() on eventfd failed: %s\n", strerror(errno));
+ }
+ }
+ }
+#endif
+
if (!f) {
- /* There were no acceptable frames on the readq. */
f = &ast_null_frame;
- if (chan->alertpipe[0] > -1) {
- int poke = 0;
- /* Restore the state of the alertpipe since we aren't ready for any
- * of the frames in the readq. */
- if (write(chan->alertpipe[1], &poke, sizeof(poke)) != sizeof(poke)) {
- ast_log(LOG_ERROR, "Failed to write to alertpipe: %s\n", strerror(errno));
- }
- }
}
/* Interpret hangup and end-of-Q frames to return NULL */
@@ -3943,21 +3934,72 @@
break;
}
}
+ } else if ((chan->fds[AST_TIMING_FD] > -1) &&
+ (chan->fdno == AST_TIMING_FD)) {
+ enum ast_timer_event res;
+
+ ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+
+ res = ast_timer_get_event(chan->timer);
+
+ switch (res) {
+ case AST_TIMING_EVENT_EXPIRED:
+ ast_timer_ack(chan->timer, 1);
+
+ if (chan->timingfunc) {
+ /* save a copy of func/data before unlocking the channel */
+ int (*func)(const void *) = chan->timingfunc;
+ void *data = chan->timingdata;
+ chan->fdno = -1;
+ ast_channel_unlock(chan);
+ func(data);
+ } else {
+ ast_timer_set_rate(chan->timer, 0);
+ chan->fdno = -1;
+ ast_channel_unlock(chan);
+ }
+
+ /* cannot 'goto done' because the channel is already unlocked */
+ return &ast_null_frame;
+
+ case AST_TIMING_EVENT_CONTINUOUS:
+ if (AST_LIST_EMPTY(&chan->readq) ||
+ !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) {
+ ast_timer_disable_continuous(chan->timer);
+ }
+ break;
+ }
+ } else if ((chan->fds[AST_GENERATOR_FD] > -1) &&
+ (chan->fdno == AST_GENERATOR_FD)) {
+ /* if the AST_GENERATOR_FD is set, call the generator with args
+ * set to -1 so it can do whatever it needs to.
+ */
+ void *tmp = chan->generatordata;
+ chan->generatordata = NULL; /* reset to let ast_write get through */
+ chan->generator->generate(chan, tmp, -1, -1);
+ chan->generatordata = tmp;
+ f = &ast_null_frame;
+ chan->fdno = -1;
+ goto done;
+ } else if ((chan->fds[AST_JITTERBUFFER_FD] > -1) &&
+ (chan->fdno == AST_JITTERBUFFER_FD)) {
+ ast_clear_flag(chan, AST_FLAG_EXCEPTION);
} else {
chan->blocker = pthread_self();
if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
- if (chan->tech->exception)
+ if (chan->tech->exception) {
f = chan->tech->exception(chan);
- else {
+ } else {
ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
f = &ast_null_frame;
}
/* Clear the exception flag */
ast_clear_flag(chan, AST_FLAG_EXCEPTION);
- } else if (chan->tech && chan->tech->read)
+ } else if (chan->tech && chan->tech->read) {
f = chan->tech->read(chan);
- else
+ } else {
ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
+ }
}
/* Perform the framehook read event here. After the frame enters the framehook list
@@ -6550,7 +6592,7 @@
*/
int ast_do_masquerade(struct ast_channel *original)
{
- int x, i;
+ int x;
int res=0;
int origstate;
int visible_indication;
@@ -6710,14 +6752,25 @@
original->tech_pvt = clonechan->tech_pvt;
clonechan->tech_pvt = t_pvt;
- /* Swap the alertpipes */
- for (i = 0; i < 2; i++) {
- x = original->alertpipe[i];
- original->alertpipe[i] = clonechan->alertpipe[i];
- clonechan->alertpipe[i] = x;
- }
-
- /*
+#ifndef HAVE_EVENTFD
+ {
+ int i;
+
+ /* Swap the alertpipes */
+ for (i = 0; i < 2; i++) {
+ x = original->alertpipe[i];
+ original->alertpipe[i] = clonechan->alertpipe[i];
+ clonechan->alertpipe[i] = x;
+ }
+ }
+#else
+ /* Swap the eventfds */
+ x = original->fds[AST_ALERT_FD];
+ original->fds[AST_ALERT_FD] = clonechan->fds[AST_ALERT_FD];
+ clonechan->fds[AST_ALERT_FD] = x;
+#endif
+
+ /*
* Swap the readq's. The end result should be this:
*
* 1) All frames should be on the new (original) channel.
@@ -6729,6 +6782,8 @@
* old (clone) channel.
*/
{
+ unsigned int moved_frames = 0;
+
AST_LIST_HEAD_NOLOCK(, ast_frame) tmp_readq;
AST_LIST_HEAD_SET_NOLOCK(&tmp_readq, NULL);
@@ -6737,14 +6792,27 @@
while ((current = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) {
AST_LIST_INSERT_TAIL(&original->readq, current, frame_list);
- if (original->alertpipe[1] > -1) {
- int poke = 0;
-
- if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) {
- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
- }
- }
- }
+ moved_frames++;
+ }
+
+#ifndef HAVE_EVENTFD
+ if (original->alertpipe[1] > -1) {
+ int poke[moved_frames];
+
+ memset(poke, 0, sizeof(poke));
+ if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) {
+ ast_log(LOG_WARNING, "write() on alertpipe failed: %s\n", strerror(errno));
+ }
+ }
+#else
+ if (original->fds[AST_ALERT_FD] > -1) {
+ uint64_t poke = moved_frames;
+
+ if (write(original->fds[AST_ALERT_FD], &poke, sizeof(poke)) < 0) {
+ ast_log(LOG_WARNING, "write() on eventfd failed: %s\n", strerror(errno));
+ }
+ }
+#endif
}
/* Swap the raw formats */
More information about the asterisk-commits
mailing list