[asterisk-commits] tilghman: branch tilghman/ast_select r281685 - in /team/tilghman/ast_select: ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Aug 10 23:59:43 CDT 2010


Author: tilghman
Date: Tue Aug 10 23:59:27 2010
New Revision: 281685

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=281685
Log:
Create a poll variation for use with chan_phone

Modified:
    team/tilghman/ast_select/channels/chan_phone.c
    team/tilghman/ast_select/include/asterisk/poll-compat.h
    team/tilghman/ast_select/main/poll.c
    team/tilghman/ast_select/res/res_features.c

Modified: team/tilghman/ast_select/channels/chan_phone.c
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/channels/chan_phone.c?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/channels/chan_phone.c (original)
+++ team/tilghman/ast_select/channels/chan_phone.c Tue Aug 10 23:59:27 2010
@@ -997,12 +997,12 @@
 
 static void *do_monitor(void *data)
 {
-	ast_fdset 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,37 @@
 		}
 		/* 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;
+				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 +1055,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 +1084,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 +1114,6 @@
 		ast_mutex_unlock(&iflock);
 	}
 	return NULL;
-	
 }
 
 static int restart_monitor()

Modified: team/tilghman/ast_select/include/asterisk/poll-compat.h
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/include/asterisk/poll-compat.h?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/include/asterisk/poll-compat.h (original)
+++ team/tilghman/ast_select/include/asterisk/poll-compat.h Tue Aug 10 23:59:27 2010
@@ -116,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: team/tilghman/ast_select/main/poll.c
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/main/poll.c?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/main/poll.c (original)
+++ team/tilghman/ast_select/main/poll.c Tue Aug 10 23:59:27 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,13 @@
 
 #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 "asterisk/poll-compat.h"							/* this package */
 
 /*---------------------------------------------------------------------------*\
 				  Macros
@@ -92,210 +90,201 @@
 #endif
 
 /*---------------------------------------------------------------------------*\
-			     Private Functions
-\*---------------------------------------------------------------------------*/
-
-static int map_poll_spec
-#if __STDC__ > 0
-			(struct pollfd *pArray,
-			  unsigned long  n_fds,
-			  ast_fdset     *pReadSet,
-			  ast_fdset     *pWriteSet,
-			  ast_fdset     *pExceptSet)
-#else
-			 (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
-			  struct pollfd *pArray;
-			  unsigned long  n_fds;
-			  ast_fdset     *pReadSet;
-			  ast_fdset     *pWriteSet;
-			  ast_fdset     *pExceptSet;
-#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)
-    {
+				 Private Functions
+\*---------------------------------------------------------------------------*/
+
+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;
+		/*
+		 * 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;
+		/*
+		 * "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,
-			  ast_fdset     *pReadSet,
-			  ast_fdset     *pWriteSet,
-			  ast_fdset     *pExceptSet)
-#else
-			 (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
-			  struct pollfd *pArray;
-			  unsigned long  n_fds;
-			  ast_fdset     *pReadSet;
-			  ast_fdset     *pWriteSet;
-			  ast_fdset     *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
-\*---------------------------------------------------------------------------*/
-
+		/* 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, 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
+\*---------------------------------------------------------------------------*/
+#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 */
-
-    FD_ZERO (&read_descs);
-    FD_ZERO (&write_descs);
-    FD_ZERO (&except_descs);
-
-    /* Map the poll() file descriptor list in the select() data structures. */
+	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 */
+
+	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,
+	/* 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);
 
-    if (ready_descriptors >= 0)
-    {
+	if (ready_descriptors >= 0) {
 		map_select_results (pArray, n_fds,
-			    &read_descs, &write_descs, &except_descs);
-    }
-
-    return ready_descriptors;
-}
-
+				&read_descs, &write_descs, &except_descs);
+	}
+
+	return ready_descriptors;
+}
 #endif /* AST_POLL_COMPAT */
+
+/* Note: we intentionally do not use the ppoll(2) call on Linux, because while the
+ * kernel modifies the tv argument, glibc hides the change from us, and we WANT to
+ * be able to check how much time remains.  Chan_phone, in particular, depends upon
+ * this behavior.
+ */
+int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
+{
+	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;
+}
+
+

Modified: team/tilghman/ast_select/res/res_features.c
URL: http://svnview.digium.com/svn/asterisk/team/tilghman/ast_select/res/res_features.c?view=diff&rev=281685&r1=281684&r2=281685
==============================================================================
--- team/tilghman/ast_select/res/res_features.c (original)
+++ team/tilghman/ast_select/res/res_features.c Tue Aug 10 23:59:27 2010
@@ -2314,7 +2314,7 @@
 				ast_indicate(chan, AST_CONTROL_UNHOLD);
 				/* Get chan, exten from derived kludge */
 				if (pu->peername[0]) {
-					char *peername = ast_strdupa(pu->peername);
+					char *peername = ast_strdup(pu->peername);
 					char *cp = strrchr(peername, '-');
 					if (cp) 
 						*cp = 0;
@@ -2351,6 +2351,7 @@
 						ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free_ptr, registrar);
 					}
 					set_c_e_p(chan, parking_con_dial, peername, 1);
+					ast_free(peername);
 				} else {
 					/* They've been waiting too long, send them back to where they came.  Theoretically they
 					   should have their original extensions and such, but we copy to be on the safe side */




More information about the asterisk-commits mailing list