aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xasterisk.c63
-rwxr-xr-xchannel.c156
-rwxr-xr-xmanager.c20
3 files changed, 138 insertions, 101 deletions
diff --git a/asterisk.c b/asterisk.c
index bc27f37dc..6566bb7b2 100755
--- a/asterisk.c
+++ b/asterisk.c
@@ -13,6 +13,7 @@
#include <unistd.h>
#include <stdlib.h>
+#include <sys/poll.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/cli.h>
@@ -229,26 +230,24 @@ static void *netconsole(void *vconsole)
char hostname[256];
char tmp[512];
int res;
- int max;
- fd_set rfds;
+ struct pollfd fds[2];
if (gethostname(hostname, sizeof(hostname)))
strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION);
fdprint(con->fd, tmp);
for(;;) {
- FD_ZERO(&rfds);
- FD_SET(con->fd, &rfds);
- FD_SET(con->p[0], &rfds);
- max = con->fd;
- if (con->p[0] > max)
- max = con->p[0];
- res = ast_select(max + 1, &rfds, NULL, NULL, NULL);
+ fds[0].fd = con->fd;
+ fds[0].events = POLLIN;
+ fds[1].fd = con->p[0];
+ fds[1].events = POLLIN;
+
+ res = poll(fds, 2, -1);
if (res < 0) {
- ast_log(LOG_WARNING, "select returned < 0: %s\n", strerror(errno));
+ ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
continue;
}
- if (FD_ISSET(con->fd, &rfds)) {
+ if (fds[0].revents) {
res = read(con->fd, tmp, sizeof(tmp));
if (res < 1) {
break;
@@ -256,7 +255,7 @@ static void *netconsole(void *vconsole)
tmp[res] = 0;
ast_cli_command(con->fd, tmp);
}
- if (FD_ISSET(con->p[0], &rfds)) {
+ if (fds[1].revents) {
res = read(con->p[0], tmp, sizeof(tmp));
if (res < 1) {
ast_log(LOG_ERROR, "read returned %d\n", res);
@@ -280,23 +279,23 @@ static void *netconsole(void *vconsole)
static void *listener(void *unused)
{
struct sockaddr_un sun;
- fd_set fds;
int s;
int len;
int x;
int flags;
+ struct pollfd fds[1];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
for(;;) {
if (ast_socket < 0)
return NULL;
- FD_ZERO(&fds);
- FD_SET(ast_socket, &fds);
- s = ast_select(ast_socket + 1, &fds, NULL, NULL, NULL);
+ fds[0].fd = ast_socket;
+ fds[0].events= POLLIN;
+ s = poll(fds, 1, -1);
if (s < 0) {
if (errno != EINTR)
- ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
+ ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
continue;
}
len = sizeof(sun);
@@ -397,7 +396,7 @@ static int ast_tryconnect(void)
static void urg_handler(int num)
{
- /* Called by soft_hangup to interrupt the select, read, or other
+ /* Called by soft_hangup to interrupt the poll, read, or other
system call. We don't actually need to do anything though. */
/* Cannot EVER ast_log from within a signal handler */
if (option_debug)
@@ -628,7 +627,7 @@ static void console_verboser(const char *s, int pos, int replace, int complete)
fputs(s + pos,stdout);
fflush(stdout);
if (complete)
- /* Wake up a select()ing console */
+ /* Wake up a poll()ing console */
if (option_console && consolethread != AST_PTHREADT_NULL)
pthread_kill(consolethread, SIGURG);
}
@@ -821,38 +820,38 @@ static struct ast_cli_entry astbang = { { "!", NULL }, handle_bang, "Execute a s
static int ast_el_read_char(EditLine *el, char *cp)
{
- int num_read=0;
+ int num_read=0;
int lastpos=0;
- fd_set rfds;
+ struct pollfd fds[2];
int res;
int max;
char buf[512];
for (;;) {
- FD_ZERO(&rfds);
- FD_SET(ast_consock, &rfds);
- max = ast_consock;
+ max = 1;
+ fds[0].fd = ast_consock;
+ fds[0].events = POLLIN;
if (!option_exec) {
- FD_SET(STDIN_FILENO, &rfds);
- if (STDIN_FILENO > max)
- max = STDIN_FILENO;
+ fds[1].fd = STDIN_FILENO;
+ fds[1].events = POLLIN;
+ max++;
}
- res = ast_select(max+1, &rfds, NULL, NULL, NULL);
+ res = poll(fds, max, -1);
if (res < 0) {
if (errno == EINTR)
continue;
- ast_log(LOG_ERROR, "select failed: %s\n", strerror(errno));
+ ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
break;
}
- if (FD_ISSET(STDIN_FILENO, &rfds)) {
+ if (!option_exec && fds[1].revents) {
num_read = read(STDIN_FILENO, cp, 1);
if (num_read < 1) {
break;
} else
return (num_read);
}
- if (FD_ISSET(ast_consock, &rfds)) {
+ if (fds[0].revents) {
res = read(ast_consock, buf, sizeof(buf) - 1);
/* if the remote side disappears exit */
if (res < 1) {
@@ -1672,7 +1671,7 @@ int main(int argc, char *argv[])
} else {
/* Do nothing */
- ast_select(0,NULL,NULL,NULL,NULL);
+ poll(NULL,0, -1);
}
return 0;
}
diff --git a/channel.c b/channel.c
index 035677b72..82d5452a0 100755
--- a/channel.c
+++ b/channel.c
@@ -20,6 +20,7 @@
#include <errno.h>
#include <unistd.h>
#include <math.h> /* For PI */
+#include <sys/poll.h>
#include <asterisk/pbx.h>
#include <asterisk/frame.h>
#include <asterisk/sched.h>
@@ -773,32 +774,40 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen,
return 0;
}
+static inline int ast_fdisset(struct pollfd *pfds, int fd, int max)
+{
+ int x;
+ for (x=0;x<max;x++)
+ if (pfds[x].fd == fd)
+ return pfds[x].revents;
+ return 0;
+}
+
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
{
/* Wait for x amount of time on a file descriptor to have input. */
- struct timeval tv;
- fd_set rfds, efds;
+ struct timeval start, now;
int res;
- int x, max=-1;
+ int x, y;
int winner = -1;
+ struct pollfd *pfds;
- tv.tv_sec = *ms / 1000;
- tv.tv_usec = (*ms % 1000) * 1000;
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
+ pfds = alloca(sizeof(struct pollfd) * n);
+ if (!pfds) {
+ ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
+ return -1;
+ }
+ if (*ms > 0)
+ gettimeofday(&start, NULL);
+ y = 0;
for (x=0;x<n;x++) {
if (fds[x] > -1) {
- FD_SET(fds[x], &rfds);
- FD_SET(fds[x], &efds);
- if (fds[x] > max)
- max = fds[x];
+ pfds[y].fd = fds[x];
+ pfds[y].events = POLLIN | POLLPRI;
+ y++;
}
}
- if (*ms >= 0)
- res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
- else
- res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
-
+ res = poll(pfds, y, *ms);
if (res < 0) {
/* Simulate a timeout if we were interrupted */
if (errno != EINTR)
@@ -807,15 +816,29 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
*ms = 0;
return -1;
}
-
for (x=0;x<n;x++) {
- if ((fds[x] > -1) && (FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && (winner < 0)) {
- if (exception)
- *exception = FD_ISSET(fds[x], &efds);
- winner = fds[x];
+ if (fds[x] > -1) {
+ if ((res = ast_fdisset(pfds, fds[x], y))) {
+ winner = fds[x];
+ if (exception) {
+ if (res & POLLPRI)
+ *exception = -1;
+ else
+ *exception = 0;
+ }
+ }
}
}
- *ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ if (*ms > 0) {
+ long passed;
+ gettimeofday(&now, NULL);
+ passed = (now.tv_sec - start.tv_sec) * 1000;
+ passed += (now.tv_usec - start.tv_usec) / 1000;
+ if (passed <= *ms)
+ *ms -= passed;
+ else
+ *ms = 0;
+ }
return winner;
}
@@ -823,13 +846,21 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
int *exception, int *outfd, int *ms)
{
/* Wait for x amount of time on a file descriptor to have input. */
- struct timeval tv;
- fd_set rfds, efds;
+ struct timeval start, end;
+ struct pollfd *pfds;
int res;
- int x, y, max=-1;
+ long rms;
+ int x, y, max;
time_t now = 0;
long whentohangup = 0, havewhen = 0, diff;
struct ast_channel *winner = NULL;
+
+ pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds));
+ if (!pfds) {
+ ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
+ *outfd = -1;
+ return NULL;
+ }
if (outfd)
*outfd = -99999;
if (exception)
@@ -857,41 +888,35 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
}
ast_mutex_unlock(&c[x]->lock);
}
-
- tv.tv_sec = *ms / 1000;
- tv.tv_usec = (*ms % 1000) * 1000;
+
+ rms = *ms;
if (havewhen) {
if ((*ms < 0) || (whentohangup * 1000 < *ms)) {
- tv.tv_sec = whentohangup;
- tv.tv_usec = 0;
+ rms = whentohangup * 1000;
}
}
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
-
+ max = 0;
for (x=0;x<n;x++) {
for (y=0;y<AST_MAX_FDS;y++) {
if (c[x]->fds[y] > -1) {
- FD_SET(c[x]->fds[y], &rfds);
- FD_SET(c[x]->fds[y], &efds);
- if (c[x]->fds[y] > max)
- max = c[x]->fds[y];
+ pfds[max].fd = c[x]->fds[y];
+ pfds[max].events = POLLIN | POLLPRI;
+ max++;
}
}
CHECK_BLOCKING(c[x]);
}
for (x=0;x<nfds; x++) {
- FD_SET(fds[x], &rfds);
- FD_SET(fds[x], &efds);
- if (fds[x] > max)
- max = fds[x];
+ if (fds[x] > -1) {
+ pfds[max].fd = fds[x];
+ pfds[max].events = POLLIN | POLLPRI;
+ max++;
+ }
}
- if ((*ms >= 0) || (havewhen))
- res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
- else
- res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
-
+ if (*ms > 0)
+ gettimeofday(&start, NULL);
+ res = poll(pfds, max, rms);
if (res < 0) {
for (x=0;x<n;x++)
c[x]->blocking = 0;
@@ -918,26 +943,41 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
}
for (y=0;y<AST_MAX_FDS;y++) {
if (c[x]->fds[y] > -1) {
- if ((FD_ISSET(c[x]->fds[y], &rfds) || FD_ISSET(c[x]->fds[y], &efds)) && !winner) {
- /* Set exception flag if appropriate */
- if (FD_ISSET(c[x]->fds[y], &efds))
+ if ((res = ast_fdisset(pfds, c[x]->fds[y], max))) {
+ if (res & POLLPRI)
c[x]->exception = 1;
- c[x]->fdno = y;
+ else
+ c[x]->exception = 0;
winner = c[x];
}
}
}
}
for (x=0;x<nfds;x++) {
- if ((FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && !winner) {
- if (outfd)
- *outfd = fds[x];
- if (FD_ISSET(fds[x], &efds) && exception)
- *exception = 1;
- winner = NULL;
- }
+ if (fds[x] > -1) {
+ if ((res = ast_fdisset(pfds, fds[x], max))) {
+ if (outfd)
+ *outfd = fds[x];
+ if (exception) {
+ if (res & POLLPRI)
+ *exception = -1;
+ else
+ *exception = 1;
+ }
+ winner = NULL;
+ }
+ }
+ }
+ if (*ms > 0) {
+ long diff;
+ gettimeofday(&end, NULL);
+ diff = (end.tv_sec - start.tv_sec) * 1000;
+ diff += (end.tv_usec - start.tv_usec) * 1000;
+ if (diff < *ms)
+ *ms -= diff;
+ else
+ *ms = 0;
}
- *ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
return winner;
}
diff --git a/manager.c b/manager.c
index b46685e3c..abef7a523 100755
--- a/manager.c
+++ b/manager.c
@@ -25,6 +25,7 @@
#include <signal.h>
#include <errno.h>
#include <unistd.h>
+#include <sys/poll.h>
#include <asterisk/channel.h>
#include <asterisk/file.h>
#include <asterisk/manager.h>
@@ -68,8 +69,7 @@ int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
/* Try to write string, but wait no more than ms milliseconds
before timing out */
int res=0;
- struct timeval tv;
- fd_set fds;
+ struct pollfd fds[1];
while(len) {
res = write(fd, s, len);
if ((res < 0) && (errno != EAGAIN)) {
@@ -78,12 +78,10 @@ int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
if (res < 0) res = 0;
len -= res;
s += res;
- tv.tv_sec = timeoutms / 1000;
- tv.tv_usec = timeoutms % 1000;
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
+ fds[0].fd = fd;
+ fds[0].events = POLLOUT;
/* Wait until writable again */
- res = select(fd + 1, NULL, &fds, NULL, &tv);
+ res = poll(fds, 1, timeoutms);
if (res < 1)
return -1;
}
@@ -715,7 +713,7 @@ static int get_input(struct mansession *s, char *output)
/* output must have at least sizeof(s->inbuf) space */
int res;
int x;
- fd_set fds;
+ struct pollfd fds[1];
for (x=1;x<s->inlen;x++) {
if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
/* Copy output data up to and including \r\n */
@@ -732,9 +730,9 @@ static int get_input(struct mansession *s, char *output)
ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", inet_ntoa(s->sin.sin_addr), s->inbuf);
s->inlen = 0;
}
- FD_ZERO(&fds);
- FD_SET(s->fd, &fds);
- res = ast_select(s->fd + 1, &fds, NULL, NULL, NULL);
+ fds[0].fd = s->fd;
+ fds[0].events = POLLIN;
+ res = poll(fds, 1, -1);
if (res < 0) {
ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
} else if (res > 0) {