[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