[asterisk-commits] tilghman: branch 1.4 r284478 - in /branches/1.4: ./ channels/ include/asteris...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Sep 1 13:49:17 CDT 2010
Author: tilghman
Date: Wed Sep 1 13:49:11 2010
New Revision: 284478
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=284478
Log:
Ensure that all areas that previously used select(2) now use poll(2), with implementations that need poll(2) implemented with select(2) safe against 1024-bit overflows.
This is a followup to the fix for the pthread timer in 1.6.2 and beyond, fixing
a potential crash bug in all supported releases.
(closes issue #17678)
Reported by: russell
Branch: https://origsvn.digium.com/svn/asterisk/team/tilghman/ast_select
Review: https://reviewboard.asterisk.org/r/824/
Added:
branches/1.4/include/asterisk/select.h
- copied unchanged from r284476, team/tilghman/ast_select/include/asterisk/select.h
branches/1.4/tests/test_poll.c (with props)
Modified:
branches/1.4/channels/chan_alsa.c
branches/1.4/channels/chan_misdn.c
branches/1.4/channels/chan_oss.c
branches/1.4/channels/chan_phone.c
branches/1.4/configure
branches/1.4/configure.ac
branches/1.4/include/asterisk/autoconfig.h.in
branches/1.4/include/asterisk/channel.h
branches/1.4/include/asterisk/poll-compat.h
branches/1.4/main/asterisk.c
branches/1.4/main/poll.c
branches/1.4/res/res_features.c
Modified: branches/1.4/channels/chan_alsa.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/channels/chan_alsa.c?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/channels/chan_alsa.c (original)
+++ branches/1.4/channels/chan_alsa.c Wed Sep 1 13:49:11 2010
@@ -277,34 +277,25 @@
static void *sound_thread(void *unused)
{
- fd_set rfds;
- fd_set wfds;
- int max, res;
+ struct pollfd pfd[3] = { { .fd = sndcmd[0], .events = POLLIN }, { .fd = writedev }, { .fd = readdev } };
+ int res, x;
for (;;) {
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- max = sndcmd[0];
- FD_SET(sndcmd[0], &rfds);
- if (cursound > -1) {
- FD_SET(writedev, &wfds);
- if (writedev > max)
- max = writedev;
- }
+ for (x = 0; x < 3; x++) {
+ pfd[x].revents = 0;
+ }
+
+ pfd[1].events = cursound > -1 ? POLLOUT : 0;
#ifdef ALSA_MONITOR
- if (!alsa.owner) {
- FD_SET(readdev, &rfds);
- if (readdev > max)
- max = readdev;
- }
-#endif
- res = ast_select(max + 1, &rfds, &wfds, NULL, NULL);
+ pfd[2].events = !alsa.owner ? POLLIN : 0;
+#endif
+ res = ast_poll(pfd, 3, -1);
if (res < 1) {
- ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
+ ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
continue;
}
#ifdef ALSA_MONITOR
- if (FD_ISSET(readdev, &rfds)) {
+ if (pfd[2].revents & POLLIN) {
/* Keep the pipe going with read audio */
snd_pcm_state_t state;
short buf[FRAME_SIZE];
@@ -329,7 +320,7 @@
alsa_monitor_read((char *) buf, r * 2);
}
#endif
- if (FD_ISSET(sndcmd[0], &rfds)) {
+ if (pfd[0].revents & POLLIN) {
if (read(sndcmd[0], &cursound, sizeof(cursound)) < 0) {
ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
}
@@ -337,9 +328,11 @@
offset = 0;
sampsent = 0;
}
- if (FD_ISSET(writedev, &wfds))
- if (send_sound())
+ if (pfd[1].revents & POLLOUT) {
+ if (send_sound()) {
ast_log(LOG_WARNING, "Failed to write sound\n");
+ }
+ }
}
/* Never reached */
return NULL;
Modified: branches/1.4/channels/chan_misdn.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/channels/chan_misdn.c?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/channels/chan_misdn.c (original)
+++ branches/1.4/channels/chan_misdn.c Wed Sep 1 13:49:11 2010
@@ -2763,9 +2763,8 @@
static struct ast_frame *misdn_read(struct ast_channel *ast)
{
struct chan_list *tmp;
- fd_set rrfs;
- struct timeval tv;
int len, t;
+ struct pollfd pfd = { .fd = -1, .events = POLLIN };
if (!ast) {
chan_misdn_log(1, 0, "misdn_read called without ast\n");
@@ -2781,30 +2780,23 @@
return NULL;
}
- tv.tv_sec=0;
- tv.tv_usec=20000;
-
- FD_ZERO(&rrfs);
- FD_SET(tmp->pipe[0],&rrfs);
-
- t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
+ pfd.fd = tmp->pipe[0];
+ t = ast_poll(&pfd, 1, 20);
+
+ if (t < 0) {
+ chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
+ return NULL;
+ }
if (!t) {
- chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
- len=160;
- }
-
- if (t<0) {
- chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
- return NULL;
- }
-
- if (FD_ISSET(tmp->pipe[0],&rrfs)) {
- len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
-
- if (len<=0) {
+ chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
+ len = 160;
+ } else if (pfd.revents & POLLIN) {
+ len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
+
+ if (len <= 0) {
/* we hangup here, since our pipe is closed */
- chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
+ chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
return NULL;
}
@@ -4910,26 +4902,22 @@
if (ch->ast)
ast_queue_frame(ch->ast, &frame);
} else {
- fd_set wrfs;
- struct timeval tv = { 0, 0 };
+ struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
int t;
- FD_ZERO(&wrfs);
- FD_SET(ch->pipe[1], &wrfs);
-
- t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
+ t = ast_poll(&pfd, 1, 0);
+
+ if (t < 0) {
+ chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
+ break;
+ }
if (!t) {
- chan_misdn_log(9, bc->port, "Select Timed out\n");
+ chan_misdn_log(9, bc->port, "poll() timed out\n");
break;
}
-
- if (t < 0) {
- chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
- break;
- }
-
- if (FD_ISSET(ch->pipe[1], &wrfs)) {
+
+ if (pfd.revents & POLLOUT) {
chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
Modified: branches/1.4/channels/chan_oss.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/channels/chan_oss.c?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/channels/chan_oss.c (original)
+++ branches/1.4/channels/chan_oss.c Wed Sep 1 13:49:11 2010
@@ -604,38 +604,32 @@
if (read(o->sounddev, ign, sizeof(ign)) < 0) {
}
for (;;) {
- fd_set rfds, wfds;
- int maxfd, res;
+ int res;
+ struct pollfd pfd[2] = { { .fd = o->sndcmd[0], .events = POLLIN }, { .fd = o->sounddev, .events = 0 } };
pthread_testcancel();
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_SET(o->sndcmd[0], &rfds);
- maxfd = o->sndcmd[0]; /* pipe from the main process */
- if (o->cursound > -1 && o->sounddev < 0)
+ if (o->cursound > -1 && o->sounddev < 0) {
setformat(o, O_RDWR); /* need the channel, try to reopen */
- else if (o->cursound == -1 && o->owner == NULL)
+ } else if (o->cursound == -1 && o->owner == NULL) {
setformat(o, O_CLOSE); /* can close */
+ }
if (o->sounddev > -1) {
if (!o->owner) { /* no one owns the audio, so we must drain it */
- FD_SET(o->sounddev, &rfds);
- maxfd = MAX(o->sounddev, maxfd);
+ pfd[1].events |= POLLIN;
}
if (o->cursound > -1) {
- FD_SET(o->sounddev, &wfds);
- maxfd = MAX(o->sounddev, maxfd);
+ pfd[1].events |= POLLOUT;
}
}
- /* ast_select emulates linux behaviour in terms of timeout handling */
- res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
+ res = ast_poll(pfd, 2, -1);
pthread_testcancel();
if (res < 1) {
- ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
+ ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
sleep(1);
continue;
}
- if (FD_ISSET(o->sndcmd[0], &rfds)) {
+ if (pfd[0].revents & POLLIN) {
/* read which sound to play from the pipe */
int i, what = -1;
@@ -656,11 +650,13 @@
ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
}
if (o->sounddev > -1) {
- if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
+ if (pfd[1].revents & POLLIN) { /* read and ignore errors */
if (read(o->sounddev, ign, sizeof(ign)) < 0) {
}
- if (FD_ISSET(o->sounddev, &wfds))
+ }
+ if (pfd[1].revents & POLLOUT) {
send_sound(o);
+ }
}
}
return NULL; /* Never reached */
Modified: branches/1.4/channels/chan_phone.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/channels/chan_phone.c?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/channels/chan_phone.c (original)
+++ branches/1.4/channels/chan_phone.c Wed Sep 1 13:49:11 2010
@@ -997,12 +997,12 @@
static void *do_monitor(void *data)
{
- fd_set rfds, efds;
- int n, res;
+ struct pollfd *fds = NULL;
+ int nfds = 0, inuse_fds = 0, res;
struct phone_pvt *i;
int tonepos = 0;
/* The tone we're playing this round */
- struct timeval tv = {0,0};
+ struct timeval tv = { 0, 0 };
int dotone;
/* This thread monitors all the frame relay interfaces which are not yet in use
(and thus do not have a separate thread) indefinitely */
@@ -1016,33 +1016,38 @@
}
/* Build the stuff we're going to select on, that is the socket of every
phone_pvt that does not have an associated owner channel */
- n = -1;
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
i = iflist;
dotone = 0;
- while (i) {
- if (FD_ISSET(i->fd, &rfds))
- ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
+ inuse_fds = 0;
+ for (i = iflist; i; i = i->next) {
if (!i->owner) {
/* This needs to be watched, as it lacks an owner */
- FD_SET(i->fd, &rfds);
- FD_SET(i->fd, &efds);
- if (i->fd > n)
- n = i->fd;
+ if (inuse_fds == nfds) {
+ void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
+ if (!tmp) {
+ /* Avoid leaking */
+ continue;
+ }
+ fds = tmp;
+ nfds++;
+ }
+ fds[inuse_fds].fd = i->fd;
+ fds[inuse_fds].events = POLLIN | POLLERR;
+ fds[inuse_fds].revents = 0;
+ inuse_fds++;
+
if (i->dialtone && i->mode != MODE_SIGMA) {
/* Remember we're going to have to come back and play
more dialtones */
if (ast_tvzero(tv)) {
/* If we're due for a dialtone, play one */
- if (write(i->fd, DialTone + tonepos, 240) != 240)
+ if (write(i->fd, DialTone + tonepos, 240) != 240) {
ast_log(LOG_WARNING, "Dial tone write error\n");
+ }
}
dotone++;
}
}
-
- i = i->next;
}
/* Okay, now that we know what to do, release the interface lock */
ast_mutex_unlock(&iflock);
@@ -1051,26 +1056,28 @@
if (dotone && i && i->mode != MODE_SIGMA) {
/* If we're ready to recycle the time, set it to 30 ms */
tonepos += 240;
- if (tonepos >= sizeof(DialTone))
- tonepos = 0;
+ if (tonepos >= sizeof(DialTone)) {
+ tonepos = 0;
+ }
if (ast_tvzero(tv)) {
- tv = ast_tv(30000, 0);
- }
- res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
+ tv = ast_tv(0, 30000);
+ }
+ res = ast_poll2(fds, inuse_fds, &tv);
} else {
- res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
- tv = ast_tv(0,0);
+ res = ast_poll(fds, inuse_fds, -1);
+ tv = ast_tv(0, 0);
tonepos = 0;
}
/* Okay, select has finished. Let's see what happened. */
if (res < 0) {
- ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno));
+ ast_log(LOG_DEBUG, "poll returned %d: %s\n", res, strerror(errno));
continue;
}
/* If there are no fd's changed, just continue, it's probably time
to play some more dialtones */
- if (!res)
+ if (!res) {
continue;
+ }
/* Alright, lock the interface list again, and let's look and see what has
happened */
if (ast_mutex_lock(&iflock)) {
@@ -1078,15 +1085,27 @@
continue;
}
- i = iflist;
- for(; i; i=i->next) {
- if (FD_ISSET(i->fd, &rfds)) {
+ for (i = iflist; i; i = i->next) {
+ int j;
+ /* Find the record */
+ for (j = 0; j < inuse_fds; j++) {
+ if (fds[j].fd == i->fd) {
+ break;
+ }
+ }
+
+ /* Not found? */
+ if (j == inuse_fds) {
+ continue;
+ }
+
+ if (fds[j].revents & POLLIN) {
if (i->owner) {
continue;
}
phone_mini_packet(i);
}
- if (FD_ISSET(i->fd, &efds)) {
+ if (fds[j].revents & POLLERR) {
if (i->owner) {
continue;
}
@@ -1096,7 +1115,6 @@
ast_mutex_unlock(&iflock);
}
return NULL;
-
}
static int restart_monitor()
Modified: branches/1.4/configure.ac
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/configure.ac?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/configure.ac (original)
+++ branches/1.4/configure.ac Wed Sep 1 13:49:11 2010
@@ -30,6 +30,7 @@
darwin*)
AC_PREFIX_DEFAULT([/usr/local])
AC_DEFINE([AST_POLL_COMPAT], 1, [Define to 1 if internal poll should be used.])
+ AC_DEFINE([_DARWIN_UNLIMITED_SELECT], 1, [Define to 1 if running on Darwin.])
;;
*)
AC_PREFIX_DEFAULT([/usr])
@@ -328,7 +329,7 @@
AC_FUNC_STRTOD
AC_FUNC_UTIME_NULL
AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf ioperm])
+AC_CHECK_FUNCS([asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow ppoll putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf ioperm])
AC_MSG_CHECKING(for timersub in time.h)
AC_LINK_IFELSE(
@@ -443,6 +444,82 @@
AC_DEFINE([HAVE_GCC_ATOMICS], 1, [Define to 1 if your GCC C compiler provides atomic operations.]),
AC_MSG_RESULT(no)
)
+
+AC_MSG_CHECKING(if we can increase the maximum select-able file descriptor)
+AC_RUN_IFELSE(
+AC_LANG_PROGRAM([
+#include <stdio.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+], [[
+ struct rlimit rlim = { FD_SETSIZE * 2, FD_SETSIZE * 2 };
+ int fd0, fd1;
+ struct timeval tv = { 0, };
+ struct ast_fdset { long fds_bits[[1024]]; } fds = { { 0, } };
+ if (setrlimit(RLIMIT_NOFILE, &rlim)) { exit(1); }
+ if ((fd0 = open("/dev/null", O_RDONLY)) < 0) { exit(1); }
+ if (dup2(fd0, (fd1 = FD_SETSIZE + 1)) < 0) { exit(1); }
+ FD_SET(fd0, (fd_set *) &fds);
+ FD_SET(fd1, (fd_set *) &fds);
+ if (select(FD_SETSIZE + 2, (fd_set *) &fds, NULL, NULL, &tv) < 0) { exit(1); }
+ exit(0)]]),
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([HAVE_VARIABLE_FDSET], 1, [Define to 1 if your system can support larger than default select bitmasks.]),
+ AC_MSG_RESULT(no),
+ AC_MSG_RESULT(cross-compile)
+)
+
+ac_cv_have_variable_fdset=0
+AC_MSG_CHECKING(if we can increase the maximum select-able file descriptor)
+AC_RUN_IFELSE(
+AC_LANG_PROGRAM([
+#include <stdio.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+], [[
+ struct rlimit rlim = { FD_SETSIZE + 2, FD_SETSIZE + 2 };
+ int fd[[2]];
+ struct timeval tv = { 0, };
+ struct ast_fdset { long fds_bits[[1024]]; } fds = { { 0, } };
+ if (setrlimit(RLIMIT_NOFILE, &rlim)) { exit(1); }
+ if ((fd0 = open("/dev/null", O_RDONLY)) < 0) { exit(1); }
+ if (dup2(fd0, (fd1 = FD_SETSIZE + 1)) < 0) { exit(1); }
+ FD_SET(fd[[0]], (fd_set *) &fds);
+ FD_SET(fd[[1]], (fd_set *) &fds);
+ if (select(FD_SETSIZE + 2, (fd_set *) &fds, NULL, NULL, &tv) < 0) { exit(1); }
+ exit(0)]]),
+ AC_MSG_RESULT(yes)
+ ac_cv_have_variable_fdset=1
+ AC_DEFINE([HAVE_VARIABLE_FDSET], 1, [Define to 1 if your system can support larger than default select bitmasks.]),
+ AC_MSG_RESULT(no),
+ AC_MSG_RESULT(cross-compile)
+)
+
+if test "${ac_cv_have_variable_fdset}x" = "0x"; then
+ AC_RUN_IFELSE(
+ AC_LANG_PROGRAM([
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdlib.h>
+], [if (getuid() != 0) { exit(1); }]),
+ 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
AST_GCC_ATTRIBUTE(pure)
AST_GCC_ATTRIBUTE(malloc)
Modified: branches/1.4/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/include/asterisk/autoconfig.h.in?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/include/asterisk/autoconfig.h.in (original)
+++ branches/1.4/include/asterisk/autoconfig.h.in Wed Sep 1 13:49:11 2010
@@ -16,6 +16,10 @@
/* Define to 1 if the `closedir' function returns void instead of `int'. */
#undef CLOSEDIR_VOID
+
+/* Some configure tests will unexpectedly fail if configure is run by a
+ non-root user. These may be able to be tested at runtime. */
+#undef CONFIGURE_RAN_AS_ROOT
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
@@ -313,6 +317,9 @@
/* Define to 1 if you have the `pow' function. */
#undef HAVE_POW
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
/* Define to 1 if you have the ISDN PRI library. */
#undef HAVE_PRI
@@ -471,7 +478,7 @@
/* Define to 1 if you have the `strtoq' function. */
#undef HAVE_STRTOQ
-/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if you have the mISDN Supplemental Services library. */
@@ -554,6 +561,10 @@
/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL
+/* Define to 1 if your system can support larger than default select bitmasks.
+ */
+#undef HAVE_VARIABLE_FDSET
+
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
@@ -660,11 +671,11 @@
/* 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
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#undef PROTOTYPES
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
@@ -684,6 +695,11 @@
/* Define to the type of arg 5 for `select'. */
#undef SELECT_TYPE_ARG5
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+ second argument and the buffer pointer as the third, as on System V before
+ release 3. */
+#undef SETVBUF_REVERSED
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
@@ -705,46 +721,53 @@
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
-/* Enable extensions on AIX 3, Interix. */
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
+
+/* Define to 1 if running on Darwin. */
+#undef _DARWIN_UNLIMITED_SELECT
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
-/* Enable threading extensions on Solaris. */
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Enable extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
-/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-#undef _LARGEFILE_SOURCE
-
-/* Define for large files, on AIX-style hosts. */
-#undef _LARGE_FILES
-
-/* Define to 1 if on MINIX. */
-#undef _MINIX
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-#undef _POSIX_1_SOURCE
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-#undef _POSIX_SOURCE
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#undef __PROTOTYPES
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
Modified: branches/1.4/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/include/asterisk/channel.h?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/include/asterisk/channel.h (original)
+++ branches/1.4/include/asterisk/channel.h Wed Sep 1 13:49:11 2010
@@ -1394,42 +1394,6 @@
}
#endif
-/*! \brief Waits for activity on a group of channels
- * \param nfds the maximum number of file descriptors in the sets
- * \param rfds file descriptors to check for read availability
- * \param wfds file descriptors to check for write availability
- * \param efds file descriptors to check for exceptions (OOB data)
- * \param tvp timeout while waiting for events
- * This is the same as a standard select(), except it guarantees the
- * behaviour where the passed struct timeval is updated with how much
- * time was not slept while waiting for the specified events
- */
-static inline int ast_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tvp)
-{
-#ifdef __linux__
- return select(nfds, rfds, wfds, efds, tvp);
-#else
- if (tvp) {
- struct timeval tv, tvstart, tvend, tvlen;
- int res;
-
- tv = *tvp;
- gettimeofday(&tvstart, NULL);
- res = select(nfds, rfds, wfds, efds, tvp);
- gettimeofday(&tvend, NULL);
- timersub(&tvend, &tvstart, &tvlen);
- timersub(&tv, &tvlen, tvp);
- if (tvp->tv_sec < 0 || (tvp->tv_sec == 0 && tvp->tv_usec < 0)) {
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
- }
- return res;
- }
- else
- return select(nfds, rfds, wfds, efds, NULL);
-#endif
-}
-
#define CHECK_BLOCKING(c) do { \
if (ast_test_flag(c, AST_FLAG_BLOCKING)) {\
if (option_debug) \
Modified: branches/1.4/include/asterisk/poll-compat.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/include/asterisk/poll-compat.h?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/include/asterisk/poll-compat.h (original)
+++ branches/1.4/include/asterisk/poll-compat.h Wed Sep 1 13:49:11 2010
@@ -79,6 +79,8 @@
#ifndef __AST_POLL_COMPAT_H
#define __AST_POLL_COMPAT_H
+#include "asterisk/select.h"
+
#ifndef AST_POLL_COMPAT
#include <sys/poll.h>
@@ -114,4 +116,10 @@
#endif /* AST_POLL_COMPAT */
+/*!
+ * \brief Same as poll(2), except the time is specified in microseconds and
+ * the tv argument is modified to indicate the time remaining.
+ */
+int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv);
+
#endif /* __AST_POLL_COMPAT_H */
Modified: branches/1.4/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/asterisk.c?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/main/asterisk.c (original)
+++ branches/1.4/main/asterisk.c Wed Sep 1 13:49:11 2010
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2009, Digium, Inc.
+ * Copyright (C) 1999 - 2010, Digium, Inc.
*
* Mark Spencer <markster at digium.com>
*
@@ -161,7 +161,6 @@
double option_maxload; /*!< Max load avg on system */
int option_maxcalls; /*!< Max number of active calls */
-
/*! @} */
char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
@@ -239,6 +238,8 @@
extern const char *ast_build_os;
extern const char *ast_build_date;
extern const char *ast_build_user;
+
+unsigned int ast_FD_SETSIZE = FD_SETSIZE;
static char *_argv[256];
static int shuttingdown;
@@ -2734,6 +2735,7 @@
int isroot = 1, rundir_exists = 0;
char *buf;
char *runuser = NULL, *rungroup = NULL;
+ struct rlimit l;
/* Remember original args for restart */
if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
@@ -2882,7 +2884,6 @@
}
if (ast_opt_dump_core) {
- struct rlimit l;
memset(&l, 0, sizeof(l));
l.rlim_cur = RLIM_INFINITY;
l.rlim_max = RLIM_INFINITY;
@@ -2890,6 +2891,44 @@
ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
}
}
+
+ if (getrlimit(RLIMIT_NOFILE, &l)) {
+ ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
+ }
+
+#if !defined(CONFIGURE_RAN_AS_ROOT)
+ /* Check if select(2) will run with more file descriptors */
+ do {
+ int fd, fd2;
+ ast_fdset readers;
+ struct timeval tv = { 0, };
+
+ if (l.rlim_cur <= FD_SETSIZE) {
+ /* The limit of select()able FDs is irrelevant, because we'll never
+ * open one that high. */
+ break;
+ }
+
+ if (!(fd = open("/dev/null", O_RDONLY))) {
+ ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
+ break; /* XXX Should we exit() here? XXX */
+ }
+
+ fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
+ if (dup2(fd, fd2)) {
+ ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
+ break;
+ }
+
+ FD_ZERO(&readers);
+ FD_SET(fd2, &readers);
+ if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
+ ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
+ }
+ } while (0);
+#elif defined(HAVE_VARIABLE_FDSET)
+ ast_FD_SETSIZE = l.rlim_cur;
+#endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
rungroup = ast_config_AST_RUN_GROUP;
Modified: branches/1.4/main/poll.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/poll.c?view=diff&rev=284478&r1=284477&r2=284478
==============================================================================
--- branches/1.4/main/poll.c (original)
+++ branches/1.4/main/poll.c Wed Sep 1 13:49:11 2010
@@ -10,9 +10,9 @@
struct pollfd
{
- int fd;
- short events;
- short revents;
+ int fd;
+ short events;
+ short revents;
}
int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
@@ -73,15 +73,14 @@
#include "asterisk.h"
-#include <unistd.h> /* standard Unix definitions */
-#include <sys/types.h> /* system types */
-#include <sys/time.h> /* time definitions */
-#include <assert.h> /* assertion macros */
-#include <string.h> /* string functions */
-
-#include "asterisk/poll-compat.h" /* this package */
-
-#ifdef AST_POLL_COMPAT
+#include <unistd.h> /* standard Unix definitions */
+#include <sys/types.h> /* system types */
+#include <sys/time.h> /* time definitions */
+#include <assert.h> /* assertion macros */
+#include <string.h> /* string functions */
+#include <errno.h>
+
+#include "asterisk/poll-compat.h" /* this package */
/*---------------------------------------------------------------------------*\
Macros
@@ -92,210 +91,214 @@
#endif
/*---------------------------------------------------------------------------*\
- Private Functions
-\*---------------------------------------------------------------------------*/
-
-static int map_poll_spec
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
+ Private Functions
+\*---------------------------------------------------------------------------*/
+
+#if defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL)
+static int map_poll_spec(struct pollfd *pArray, unsigned long n_fds,
+ ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
+{
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
+ register int max_fd = -1; /* return value */
+
+ /*
+ * Map the poll() structures into the file descriptor sets required
+ * by select().
+ */
+ for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
+ /* Skip any bad FDs in the array. */
+
+ if (pCur->fd < 0) {
+ continue;
+ }
+
+ if (pCur->events & POLLIN) {
+ /* "Input Ready" notification desired. */
+ FD_SET(pCur->fd, pReadSet);
+ }
+
+ if (pCur->events & POLLOUT) {
+ /* "Output Possible" notification desired. */
+ FD_SET(pCur->fd, pWriteSet);
+ }
+
+ if (pCur->events & POLLPRI) {
+ /*
+ * "Exception Occurred" notification desired. (Exceptions
+ * include out of band data.
+ */
+ FD_SET(pCur->fd, pExceptSet);
+ }
+
+ max_fd = MAX(max_fd, pCur->fd);
+ }
+
+ return max_fd;
+}
+
+#ifdef AST_POLL_COMPAT
+static struct timeval *map_timeout(int poll_timeout, struct timeval *pSelTimeout)
+{
+ struct timeval *pResult;
+
+ /*
+ Map the poll() timeout value into a select() timeout. The possible
+ values of the poll() timeout value, and their meanings, are:
+
+ VALUE MEANING
+
+ -1 wait indefinitely (until signal occurs)
+ 0 return immediately, don't block
+ >0 wait specified number of milliseconds
+
+ select() uses a "struct timeval", which specifies the timeout in
+ seconds and microseconds, so the milliseconds value has to be mapped
+ accordingly.
+ */
+
+ assert(pSelTimeout != NULL);
+
+ switch (poll_timeout) {
+ case -1:
+ /*
+ * A NULL timeout structure tells select() to wait indefinitely.
+ */
+ pResult = (struct timeval *) NULL;
+ break;
+
+ case 0:
+ /*
+ * "Return immediately" (test) is specified by all zeros in
+ * a timeval structure.
+ */
+ pSelTimeout->tv_sec = 0;
+ pSelTimeout->tv_usec = 0;
+ pResult = pSelTimeout;
+ break;
+
+ default:
+ /* Wait the specified number of milliseconds. */
+ pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */
+ poll_timeout %= 1000; /* remove seconds */
+ pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
+ pResult = pSelTimeout;
+ break;
+ }
+
+ return pResult;
+}
+#endif /* AST_POLL_COMPAT */
+
+static void map_select_results(struct pollfd *pArray, unsigned long n_fds,
+ ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
+{
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
+
+ for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
+ /* Skip any bad FDs in the array. */
+
+ if (pCur->fd < 0) {
+ continue;
+ }
+
+ /* Exception events take priority over input events. */
+ pCur->revents = 0;
+ if (FD_ISSET(pCur->fd, (fd_set *) pExceptSet)) {
+ pCur->revents |= POLLPRI;
+ } else if (FD_ISSET(pCur->fd, (fd_set *) pReadSet)) {
+ pCur->revents |= POLLIN;
+ }
+
+ if (FD_ISSET(pCur->fd, (fd_set *) pWriteSet)) {
+ pCur->revents |= POLLOUT;
+ }
+ }
+
+ return;
+}
+#endif /* defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL) */
+
+/*---------------------------------------------------------------------------*\
+ Public Functions
+\*---------------------------------------------------------------------------*/
+#ifdef AST_POLL_COMPAT
+int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
+{
+ ast_fdset read_descs; /* input file descs */
+ ast_fdset write_descs; /* output file descs */
+ ast_fdset except_descs; /* exception descs */
+ struct timeval stime; /* select() timeout value */
+ int ready_descriptors; /* function result */
+ int max_fd = 0; /* maximum fd value */
+ struct timeval *pTimeout; /* actually passed */
+ int save_errno;
+
+ FD_ZERO(&read_descs);
+ FD_ZERO(&write_descs);
+ FD_ZERO(&except_descs);
+
+ /* Map the poll() file descriptor list in the select() data structures. */
+
+ if (pArray) {
+ max_fd = map_poll_spec (pArray, n_fds,
+ &read_descs, &write_descs, &except_descs);
+ }
+
+ /* Map the poll() timeout value in the select() timeout structure. */
+
+ pTimeout = map_timeout (timeout, &stime);
+
+ /* Make the select() call. */
+
+ ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs,
+ &except_descs, pTimeout);
+ save_errno = errno;
+
+ if (ready_descriptors >= 0) {
+ map_select_results (pArray, n_fds,
+ &read_descs, &write_descs, &except_descs);
+ }
+
+ errno = save_errno;
+ return ready_descriptors;
+}
+#endif /* AST_POLL_COMPAT */
+
+int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
+{
+#ifdef HAVE_PPOLL
+ struct timeval start = ast_tvnow();
+ struct timespec ts = { tv ? tv->tv_sec : 0, tv ? tv->tv_usec * 1000 : 0 };
+ int res = ppoll(pArray, n_fds, tv ? &ts : NULL, NULL);
+ struct timeval after = ast_tvnow();
+ if (res > 0 && tv && ast_tvdiff_ms(ast_tvadd(*tv, start), after) > 0) {
+ *tv = ast_tvsub(*tv, ast_tvsub(after, start));
+ } else if (res > 0 && tv) {
+ *tv = ast_tv(0, 0);
+ }
+ return res;
#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
+ ast_fdset read_descs, write_descs, except_descs;
+ int ready_descriptors, max_fd = 0;
+
+ FD_ZERO(&read_descs);
+ FD_ZERO(&write_descs);
+ FD_ZERO(&except_descs);
+
+ if (pArray) {
+ max_fd = map_poll_spec(pArray, n_fds, &read_descs, &write_descs, &except_descs);
+ }
+
+ ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs, &except_descs, tv);
+
+ if (ready_descriptors >= 0) {
+ map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs);
+ }
+
+ return ready_descriptors;
#endif
-{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
- register int max_fd = -1; /* return value */
-
- /*
- Map the poll() structures into the file descriptor sets required
- by select().
- */
- for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
- {
- /* Skip any bad FDs in the array. */
-
- if (pCur->fd < 0)
- continue;
-
- if (pCur->events & POLLIN)
- {
- /* "Input Ready" notification desired. */
- FD_SET (pCur->fd, pReadSet);
- }
-
- if (pCur->events & POLLOUT)
- {
- /* "Output Possible" notification desired. */
- FD_SET (pCur->fd, pWriteSet);
- }
-
- if (pCur->events & POLLPRI)
- {
- /*
- "Exception Occurred" notification desired. (Exceptions
- include out of band data.
- */
- FD_SET (pCur->fd, pExceptSet);
- }
-
- max_fd = MAX (max_fd, pCur->fd);
- }
-
- return max_fd;
-}
-
-static struct timeval *map_timeout
-#if __STDC__ > 0
- (int poll_timeout, struct timeval *pSelTimeout)
-#else
- (poll_timeout, pSelTimeout)
- int poll_timeout;
- struct timeval *pSelTimeout;
-#endif
-{
- struct timeval *pResult;
-
- /*
- Map the poll() timeout value into a select() timeout. The possible
- values of the poll() timeout value, and their meanings, are:
-
- VALUE MEANING
-
- -1 wait indefinitely (until signal occurs)
- 0 return immediately, don't block
- >0 wait specified number of milliseconds
-
- select() uses a "struct timeval", which specifies the timeout in
- seconds and microseconds, so the milliseconds value has to be mapped
- accordingly.
- */
-
- assert (pSelTimeout != (struct timeval *) NULL);
-
- switch (poll_timeout)
- {
- case -1:
- /*
- A NULL timeout structure tells select() to wait indefinitely.
- */
- pResult = (struct timeval *) NULL;
- break;
-
- case 0:
- /*
- "Return immediately" (test) is specified by all zeros in
- a timeval structure.
- */
- pSelTimeout->tv_sec = 0;
- pSelTimeout->tv_usec = 0;
- pResult = pSelTimeout;
- break;
-
- default:
- /* Wait the specified number of milliseconds. */
- pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */
- poll_timeout %= 1000; /* remove seconds */
- pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
- pResult = pSelTimeout;
- break;
- }
-
-
- return pResult;
-}
-
-static void map_select_results
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
-#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
-#endif
-{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
-
- for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
- {
- /* Skip any bad FDs in the array. */
-
- if (pCur->fd < 0)
- continue;
-
- /* Exception events take priority over input events. */
-
- pCur->revents = 0;
- if (FD_ISSET (pCur->fd, pExceptSet))
- pCur->revents |= POLLPRI;
-
- else if (FD_ISSET (pCur->fd, pReadSet))
- pCur->revents |= POLLIN;
-
- if (FD_ISSET (pCur->fd, pWriteSet))
- pCur->revents |= POLLOUT;
- }
-
- return;
-}
-
-/*---------------------------------------------------------------------------*\
- Public Functions
-\*---------------------------------------------------------------------------*/
-
-int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
-{
- fd_set read_descs; /* input file descs */
- fd_set write_descs; /* output file descs */
- fd_set except_descs; /* exception descs */
- struct timeval stime; /* select() timeout value */
- int ready_descriptors; /* function result */
- int max_fd = 0; /* maximum fd value */
- struct timeval *pTimeout; /* actually passed */
-
- FD_ZERO (&read_descs);
- FD_ZERO (&write_descs);
- FD_ZERO (&except_descs);
-
[... 582 lines stripped ...]
More information about the asterisk-commits
mailing list