[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