[Asterisk-Dev] Some select(2) usage Linux specific, take 2

Thorsten Lockert tholo at sigmasoft.com
Sat Apr 26 06:56:35 MST 2003


This patch is a bit more invasive, but it does create a wrapper
ast_select for select(2) which on Linux systems just calls select,
while on other systems it will also do calculations on the passed
timeval to match what a Linux kernel does.

Note 1: Even the Linux manpage for select(2) suggests *NOT* expecting
	a known value in the passed timeval after doing select.

Note 2: The POSIX definition of select(2) does *NOT* specify that
	the timeval will be usable for anything after calling select

Index: asterisk.c
===================================================================
RCS file: /usr/cvsroot/asterisk/asterisk.c,v
retrieving revision 1.5
diff -u -r1.5 asterisk.c
--- asterisk.c	23 Apr 2003 20:22:14 -0000	1.5
+++ asterisk.c	26 Apr 2003 13:58:22 -0000
@@ -130,7 +130,7 @@
 		max = con->fd;
 		if (con->p[0] > max)
 			max = con->p[0];
-		res = select(max + 1, &rfds, NULL, NULL, NULL);
+		res = ast_select(max + 1, &rfds, NULL, NULL, NULL);
 		if (res < 0) {
 			ast_log(LOG_WARNING, "select returned < 0: %s\n", strerror(errno));
 			continue;
@@ -672,7 +676,7 @@
 		max = ast_consock;
 		if (STDIN_FILENO > max)
 			max = STDIN_FILENO;
-		res = select(max+1, &rfds, NULL, NULL, NULL);
+		res = ast_select(max+1, &rfds, NULL, NULL, NULL);
 		if (res < 0) {
 			if (errno == EINTR)
 				continue;
@@ -1369,7 +1373,7 @@
 
 	} else {
  		/* Do nothing */
-		select(0,NULL,NULL,NULL,NULL);
+		ast_select(0,NULL,NULL,NULL,NULL);
 	}
 	return 0;
 }
Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.11
diff -u -r1.11 channel.c
--- channel.c	17 Apr 2003 02:52:53 -0000	1.11
+++ channel.c	26 Apr 2003 13:58:24 -0000
@@ -74,6 +74,32 @@
    
 static pthread_mutex_t chlock = AST_MUTEX_INITIALIZER;
 
+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, tv);
+#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(nfds, rfds, wfds, efds, NULL);
+#endif
+}
+
 int ast_check_hangup(struct ast_channel *chan)
 {
 time_t	myt;
@@ -756,10 +782,10 @@
 				max = fds[x];
 		}
 	}
-	if (*ms >= 0) 
-		res = select(max + 1, &rfds, NULL, &efds, &tv);
+	if (*ms >= 0)
+		res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
 	else
-		res = select(max + 1, &rfds, NULL, &efds, NULL);
+		res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
 
 	if (res < 0) {
 		/* Simulate a timeout if we were interrupted */
@@ -828,10 +854,10 @@
 		if (fds[x] > max)
 			max = fds[x];
 	}
-	if (*ms >= 0) 
-		res = select(max + 1, &rfds, NULL, &efds, &tv);
+	if (*ms >= 0)
+		res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
 	else
-		res = select(max + 1, &rfds, NULL, &efds, NULL);
+		res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
 
 	if (res < 0) {
 		for (x=0;x<n;x++) 
Index: manager.c
===================================================================
RCS file: /usr/cvsroot/asterisk/manager.c,v
retrieving revision 1.7
diff -u -r1.7 manager.c
--- manager.c	14 Apr 2003 18:47:36 -0000	1.7
+++ manager.c	26 Apr 2003 13:58:25 -0000
@@ -539,7 +539,7 @@
 	}
 	FD_ZERO(&fds);
 	FD_SET(s->fd, &fds);
-	res = select(s->fd + 1, &fds, NULL, NULL, NULL);
+	res = ast_select(s->fd + 1, &fds, NULL, NULL, NULL);
 	if (res < 0) {
 		ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
 	} else if (res > 0) {
Index: apps/app_mp3.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_mp3.c,v
retrieving revision 1.3
diff -u -r1.3 app_mp3.c
--- apps/app_mp3.c	23 Apr 2003 04:39:18 -0000	1.3
+++ apps/app_mp3.c	26 Apr 2003 13:58:26 -0000
@@ -75,7 +75,7 @@
 	struct timeval tv = { 2, 0 };		/* Wait no more than 2 seconds */
 	FD_ZERO(&fds);
 	FD_SET(fd, &fds);
-	res = select(fd + 1, &fds, NULL, NULL, &tv);
+	res = ast_select(fd + 1, &fds, NULL, NULL, &tv);
 	if (res < 1) {
 		ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
 		return -1;
Index: channels/chan_alsa.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_alsa.c,v
retrieving revision 1.3
diff -u -r1.3 chan_alsa.c
--- channels/chan_alsa.c	12 Apr 2003 22:26:09 -0000	1.3
+++ channels/chan_alsa.c	26 Apr 2003 13:58:32 -0000
@@ -262,7 +262,7 @@
 				max = readdev;
 		}
 #endif
-		res = select(max + 1, &rfds, &wfds, NULL, NULL);
+		res = ast_select(max + 1, &rfds, &wfds, NULL, NULL);
 		if (res < 1) {
 			ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
 			continue;
Index: channels/chan_modem.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_modem.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 chan_modem.c
--- channels/chan_modem.c	12 Feb 2003 13:59:14 -0000	1.1.1.1
+++ channels/chan_modem.c	26 Apr 2003 13:58:53 -0000
@@ -609,7 +609,7 @@
 #endif
 		/* Wait indefinitely for something to happen */
 		pthread_testcancel();
-		res = select(n + 1, &rfds, NULL, &efds, NULL);
+		res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
 		pthread_testcancel();
 		/* Okay, select has finished.  Let's see what happened.  */
 		if (res < 1) {
Index: channels/chan_oss.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_oss.c,v
retrieving revision 1.3
diff -u -r1.3 chan_oss.c
--- channels/chan_oss.c	23 Apr 2003 20:23:30 -0000	1.3
+++ channels/chan_oss.c	26 Apr 2003 13:58:56 -0000
@@ -245,7 +245,7 @@
 			if (sounddev > max)
 				max = sounddev;
 		}
-		res = select(max + 1, &rfds, &wfds, NULL, NULL);
+		res = ast_select(max + 1, &rfds, &wfds, NULL, NULL);
 		if (res < 1) {
 			ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
 			continue;
Index: channels/chan_phone.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_phone.c,v
retrieving revision 1.4
diff -u -r1.4 chan_phone.c
--- channels/chan_phone.c	7 Apr 2003 19:14:24 -0000	1.4
+++ channels/chan_phone.c	26 Apr 2003 13:58:57 -0000
@@ -848,9 +848,9 @@
 				tv.tv_usec = 30000;
 				tv.tv_sec = 0;
 			}
-			res = select(n + 1, &rfds, NULL, &efds, &tv);
+			res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
 		} else {
-			res = select(n + 1, &rfds, NULL, &efds, NULL);
+			res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
 			tv.tv_usec = 0;
 			tv.tv_sec = 0;
 			tonepos = 0;
Index: channels/chan_vofr.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_vofr.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 chan_vofr.c
--- channels/chan_vofr.c	12 Feb 2003 13:59:14 -0000	1.1.1.1
+++ channels/chan_vofr.c	26 Apr 2003 13:59:03 -0000
@@ -564,7 +564,7 @@
 			fd_set fds;
 			FD_ZERO(&fds);
 			FD_SET(p->s, &fds);
-			select(p->s + 1, &fds, NULL, NULL, NULL);
+			ast_select(p->s + 1, &fds, NULL, NULL, NULL);
 			goto retry;
 		}
 		ast->blocking = 0;
@@ -953,7 +953,7 @@
 		ast_pthread_mutex_unlock(&monlock);
 		pthread_testcancel();
 		/* Wait indefinitely for something to happen */
-		res = select(n + 1, &rfds, NULL, NULL, NULL);
+		res = ast_select(n + 1, &rfds, NULL, NULL, NULL);
 		pthread_testcancel();
 		/* Okay, select has finished.  Let's see what happened.  */
 		if (res < 0) {
Index: channels/chan_zap.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_zap.c,v
retrieving revision 1.38
diff -u -r1.38 chan_zap.c
--- channels/chan_zap.c	25 Apr 2003 18:44:56 -0000	1.38
+++ channels/chan_zap.c	26 Apr 2003 13:59:16 -0000
@@ -1863,7 +1863,7 @@
 				FD_ZERO(&efds);
 				FD_SET(fd,&wfds);
 				FD_SET(fd,&efds);			
-				res = select(fd + 1,NULL,&wfds,&efds,NULL);
+				res = ast_select(fd + 1,NULL,&wfds,&efds,NULL);
 				if (!res) {
 					ast_log(LOG_DEBUG, "select (for write) ret. 0 on channel %d\n", p->channel);
 					continue;
@@ -4417,7 +4417,7 @@
 		/* Wait at least a second for something to happen */
 		tv.tv_sec = 1;
 		tv.tv_usec = 0;
-		res = select(n + 1, &rfds, NULL, &efds, &tv);
+		res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
 		pthread_testcancel();
 		/* Okay, select has finished.  Let's see what happened.  */
 		if (res < 0) {
@@ -5447,7 +5447,7 @@
 		pthread_mutex_unlock(&pri->lock);
 
 		e = NULL;
-		res = select(pri->fd + 1, &rfds, NULL, &efds, &tv);
+		res = ast_select(pri->fd + 1, &rfds, NULL, &efds, &tv);
 
 		ast_pthread_mutex_lock(&pri->lock);
 		if (!res) {
@@ -6982,7 +6982,7 @@
 		FD_ZERO(&efds);
 		FD_SET(fd,&wfds);
 		FD_SET(fd,&efds);			
-		res = select(fd + 1,NULL,&wfds,&efds,NULL);
+		res = ast_select(fd + 1,NULL,&wfds,&efds,NULL);
 		if (!res) {
 			ast_log(LOG_DEBUG, "select (for write) ret. 0 on channel %d\n", p->channel);
 			continue;
Index: channels/chan_zap_old.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_zap_old.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 chan_zap_old.c
--- channels/chan_zap_old.c	12 Feb 2003 13:59:14 -0000	1.1.1.1
+++ channels/chan_zap_old.c	26 Apr 2003 13:59:26 -0000
@@ -1673,7 +1673,7 @@
 				FD_ZERO(&efds);
 				FD_SET(fd,&wfds);
 				FD_SET(fd,&efds);			
-				res = select(fd + 1,NULL,&wfds,&efds,NULL);
+				res = ast_select(fd + 1,NULL,&wfds,&efds,NULL);
 				if (!res) {
 					ast_log(LOG_DEBUG, "select (for write) ret. 0 on channel %d\n", p->channel);
 					continue;
@@ -4055,7 +4055,7 @@
 		/* Wait at least a second for something to happen */
 		tv.tv_sec = 1;
 		tv.tv_usec = 0;
-		res = select(n + 1, &rfds, NULL, &efds, &tv);
+		res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
 		pthread_testcancel();
 		/* Okay, select has finished.  Let's see what happened.  */
 		if (res < 0) {
@@ -5114,7 +5114,7 @@
 		pthread_mutex_unlock(&pri->lock);
 
 		e = NULL;
-		res = select(pri->fd + 1, &rfds, NULL, &efds, &tv);
+		res = ast_select(pri->fd + 1, &rfds, NULL, &efds, &tv);
 
 		ast_pthread_mutex_lock(&pri->lock);
 		if (!res) {
@@ -6550,7 +6550,7 @@
 		FD_ZERO(&efds);
 		FD_SET(fd,&wfds);
 		FD_SET(fd,&efds);			
-		res = select(fd + 1,NULL,&wfds,&efds,NULL);
+		res = ast_select(fd + 1,NULL,&wfds,&efds,NULL);
 		if (!res) {
 			ast_log(LOG_DEBUG, "select (for write) ret. 0 on channel %d\n", p->channel);
 			continue;
Index: include/asterisk/channel.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/channel.h,v
retrieving revision 1.6
diff -u -r1.6 channel.h
--- include/asterisk/channel.h	16 Apr 2003 02:47:03 -0000	1.6
+++ include/asterisk/channel.h	26 Apr 2003 13:59:32 -0000
@@ -422,6 +422,19 @@
 
 //! 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
+ */
+int ast_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tvp);
+
+//! Waits for activity on a group of channels
+/*! 
  * \param chan an array of pointers to channels
  * \param n number of channels that are to be waited upon
  * \param fds an array of fds to wait upon
Index: res/res_parking.c
===================================================================
RCS file: /usr/cvsroot/asterisk/res/res_parking.c,v
retrieving revision 1.2
diff -u -r1.2 res_parking.c
--- res/res_parking.c	9 Apr 2003 04:00:43 -0000	1.2
+++ res/res_parking.c	26 Apr 2003 13:59:33 -0000
@@ -443,7 +443,7 @@
 		tv.tv_sec = ms / 1000;
 		tv.tv_usec = (ms % 1000) * 1000;
 		/* Wait for something to happen */
-		select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
+		ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
 		pthread_testcancel();
 	}
 	return NULL;	/* Never reached */
--
Thorsten Lockert      | tholo at sigmasoft.com | Universe, n.:
2121 N. Lakeshore Dr. | tholo at openbsd.org   |         The problem.
Chapel Hill, NC 27514 |                     |



More information about the asterisk-dev mailing list