diff options
-rwxr-xr-x | asterisk.c | 63 | ||||
-rwxr-xr-x | channel.c | 156 | ||||
-rwxr-xr-x | manager.c | 20 |
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; } @@ -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; } @@ -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) { |