Merged revisions 284597 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.8

................
  r284597 | tilghman | 2010-09-02 00:00:34 -0500 (Thu, 02 Sep 2010) | 29 lines
  
  Merged revisions 284593,284595 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.6.2
  
  ................
    r284593 | tilghman | 2010-09-01 17:59:50 -0500 (Wed, 01 Sep 2010) | 18 lines
    
    Merged revisions 284478 via svnmerge from 
    https://origsvn.digium.com/svn/asterisk/branches/1.4
    
    ........
      r284478 | tilghman | 2010-09-01 13:49:11 -0500 (Wed, 01 Sep 2010) | 11 lines
      
      Ensure that all areas that previously used select(2) now use poll(2), with implementations that need poll(2) implemented with select(2) safe against 1024-bit overflows.
      
      This is a followup to the fix for the pthread timer in 1.6.2 and beyond, fixing
      a potential crash bug in all supported releases.
      
      (closes issue #17678)
       Reported by: russell
      Branch: https://origsvn.digium.com/svn/asterisk/team/tilghman/ast_select 
      
      Review: https://reviewboard.asterisk.org/r/824/
    ........
  ................
    r284595 | tilghman | 2010-09-01 22:57:43 -0500 (Wed, 01 Sep 2010) | 2 lines
    
    Failed to rerun bootstrap.sh after last commit
  ................
................


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@284598 65c4cc65-6c06-0410-ace0-fbb531ad65f3
10-digiumphones
Tilghman Lesher 15 years ago
parent c28c620936
commit 5eae9f44f7

@ -23,6 +23,7 @@
#define _OOSOCKET_H_ #define _OOSOCKET_H_
#include "asterisk/poll-compat.h" #include "asterisk/poll-compat.h"
#include "asterisk/compiler.h"
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
#include <winsock.h> #include <winsock.h>
@ -331,7 +332,7 @@ EXTERN int ooSocketSendTo(OOSOCKET socket, const ASN1OCTET* pdata,
* negative return value is error. * negative return value is error.
*/ */
EXTERN int ooSocketSelect(int nfds, fd_set *readfds, fd_set *writefds, EXTERN int ooSocketSelect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval * timeout); fd_set *exceptfds, struct timeval * timeout) __attribute_deprecated__;
EXTERN int ooSocketPoll(struct pollfd *pfds, int nfds, int timeout); EXTERN int ooSocketPoll(struct pollfd *pfds, int nfds, int timeout);

@ -15,6 +15,7 @@
*****************************************************************************/ *****************************************************************************/
#include "asterisk.h" #include "asterisk.h"
#include "asterisk/lock.h" #include "asterisk/lock.h"
#include "asterisk/poll-compat.h"
#include "ooports.h" #include "ooports.h"
#include "oochannels.h" #include "oochannels.h"
@ -1980,21 +1981,11 @@ int ooStopMonitorCalls()
OOBOOL ooChannelsIsConnectionOK(OOH323CallData *call, OOSOCKET sock) OOBOOL ooChannelsIsConnectionOK(OOH323CallData *call, OOSOCKET sock)
{ {
struct timeval to; struct timeval to = { .tv_usec = 500 };
fd_set readfds; struct pollfd pfds = { .fd = sock, .events = POLLIN };
int ret = 0, nfds=0; int ret = 0;
to.tv_sec = 0;
to.tv_usec = 500;
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
if(nfds < (int)sock)
nfds = (int)sock;
nfds++;
ret = ooSocketSelect(nfds, &readfds, NULL, NULL, &to); ret = ast_poll2(&pfds, 1, &to);
if(ret == -1) if(ret == -1)
{ {

@ -7160,9 +7160,8 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
static struct ast_frame *misdn_read(struct ast_channel *ast) static struct ast_frame *misdn_read(struct ast_channel *ast)
{ {
struct chan_list *tmp; struct chan_list *tmp;
fd_set rrfs;
struct timeval tv = { 0, 20000 };
int len, t; int len, t;
struct pollfd pfd = { .fd = -1, .events = POLLIN };
if (!ast) { if (!ast) {
chan_misdn_log(1, 0, "misdn_read called without ast\n"); chan_misdn_log(1, 0, "misdn_read called without ast\n");
@ -7178,21 +7177,18 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
return NULL; return NULL;
} }
FD_ZERO(&rrfs); pfd.fd = tmp->pipe[0];
FD_SET(tmp->pipe[0], &rrfs); t = ast_poll(&pfd, 1, 20);
t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv);
if (!t) {
chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
len = 160;
}
if (t < 0) { if (t < 0) {
chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n", strerror(errno)); chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
return NULL; return NULL;
} }
if (FD_ISSET(tmp->pipe[0], &rrfs)) { if (!t) {
chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
len = 160;
} else if (pfd.revents & POLLIN) {
len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf)); len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
if (len <= 0) { if (len <= 0) {
@ -10456,25 +10452,21 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ast_queue_frame(ch->ast, &frame); ast_queue_frame(ch->ast, &frame);
} }
} else { } else {
fd_set wrfs; struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
struct timeval tv = { 0, 0 };
int t; int t;
FD_ZERO(&wrfs); t = ast_poll(&pfd, 1, 0);
FD_SET(ch->pipe[1], &wrfs);
t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv); if (t < 0) {
if (!t) { chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
chan_misdn_log(9, bc->port, "Select Timed out\n");
break; break;
} }
if (!t) {
if (t < 0) { chan_misdn_log(9, bc->port, "poll() timed out\n");
chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
break; break;
} }
if (FD_ISSET(ch->pipe[1], &wrfs)) { if (pfd.revents & POLLOUT) {
chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len); chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) { if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno)); chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));

@ -1017,12 +1017,12 @@ static void phone_check_exception(struct phone_pvt *i)
static void *do_monitor(void *data) static void *do_monitor(void *data)
{ {
fd_set rfds, efds; struct pollfd *fds = NULL;
int n, res; int nfds = 0, inuse_fds = 0, res;
struct phone_pvt *i; struct phone_pvt *i;
int tonepos = 0; int tonepos = 0;
/* The tone we're playing this round */ /* The tone we're playing this round */
struct timeval wait = {0,0}; struct timeval tv = { 0, 0 };
int dotone; int dotone;
/* This thread monitors all the frame relay interfaces which are not yet in use /* This thread monitors all the frame relay interfaces which are not yet in use
(and thus do not have a separate thread) indefinitely */ (and thus do not have a separate thread) indefinitely */
@ -1036,33 +1036,38 @@ static void *do_monitor(void *data)
} }
/* Build the stuff we're going to select on, that is the socket of every /* 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 */ phone_pvt that does not have an associated owner channel */
n = -1;
FD_ZERO(&rfds);
FD_ZERO(&efds);
i = iflist; i = iflist;
dotone = 0; dotone = 0;
while (i) { inuse_fds = 0;
if (FD_ISSET(i->fd, &rfds)) for (i = iflist; i; i = i->next) {
ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
if (!i->owner) { if (!i->owner) {
/* This needs to be watched, as it lacks an owner */ /* This needs to be watched, as it lacks an owner */
FD_SET(i->fd, &rfds); if (inuse_fds == nfds) {
FD_SET(i->fd, &efds); void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
if (i->fd > n) if (!tmp) {
n = i->fd; /* Avoid leaking */
continue;
}
fds = tmp;
nfds++;
}
fds[inuse_fds].fd = i->fd;
fds[inuse_fds].events = POLLIN | POLLERR;
fds[inuse_fds].revents = 0;
inuse_fds++;
if (i->dialtone && i->mode != MODE_SIGMA) { if (i->dialtone && i->mode != MODE_SIGMA) {
/* Remember we're going to have to come back and play /* Remember we're going to have to come back and play
more dialtones */ more dialtones */
if (ast_tvzero(wait)) { if (ast_tvzero(tv)) {
/* If we're due for a dialtone, play one */ /* 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"); ast_log(LOG_WARNING, "Dial tone write error\n");
} }
}
dotone++; dotone++;
} }
} }
i = i->next;
} }
/* Okay, now that we know what to do, release the interface lock */ /* Okay, now that we know what to do, release the interface lock */
ast_mutex_unlock(&iflock); ast_mutex_unlock(&iflock);
@ -1071,26 +1076,28 @@ static void *do_monitor(void *data)
if (dotone && i && i->mode != MODE_SIGMA) { if (dotone && i && i->mode != MODE_SIGMA) {
/* If we're ready to recycle the time, set it to 30 ms */ /* If we're ready to recycle the time, set it to 30 ms */
tonepos += 240; tonepos += 240;
if (tonepos >= sizeof(DialTone)) if (tonepos >= sizeof(DialTone)) {
tonepos = 0; tonepos = 0;
if (ast_tvzero(wait)) {
wait = ast_tv(30000, 0);
} }
res = ast_select(n + 1, &rfds, NULL, &efds, &wait); if (ast_tvzero(tv)) {
tv = ast_tv(0, 30000);
}
res = ast_poll2(fds, inuse_fds, &tv);
} else { } else {
res = ast_select(n + 1, &rfds, NULL, &efds, NULL); res = ast_poll(fds, inuse_fds, -1);
wait = ast_tv(0,0); tv = ast_tv(0, 0);
tonepos = 0; tonepos = 0;
} }
/* Okay, select has finished. Let's see what happened. */ /* Okay, select has finished. Let's see what happened. */
if (res < 0) { if (res < 0) {
ast_debug(1, "select return %d: %s\n", res, strerror(errno)); ast_debug(1, "poll returned %d: %s\n", res, strerror(errno));
continue; continue;
} }
/* If there are no fd's changed, just continue, it's probably time /* If there are no fd's changed, just continue, it's probably time
to play some more dialtones */ to play some more dialtones */
if (!res) if (!res) {
continue; continue;
}
/* Alright, lock the interface list again, and let's look and see what has /* Alright, lock the interface list again, and let's look and see what has
happened */ happened */
if (ast_mutex_lock(&iflock)) { if (ast_mutex_lock(&iflock)) {
@ -1098,15 +1105,27 @@ static void *do_monitor(void *data)
continue; continue;
} }
i = iflist; for (i = iflist; i; i = i->next) {
for(; i; i=i->next) { int j;
if (FD_ISSET(i->fd, &rfds)) { /* 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) { if (i->owner) {
continue; continue;
} }
phone_mini_packet(i); phone_mini_packet(i);
} }
if (FD_ISSET(i->fd, &efds)) { if (fds[j].revents & POLLERR) {
if (i->owner) { if (i->owner) {
continue; continue;
} }
@ -1116,7 +1135,6 @@ static void *do_monitor(void *data)
ast_mutex_unlock(&iflock); ast_mutex_unlock(&iflock);
} }
return NULL; return NULL;
} }
static int restart_monitor() static int restart_monitor()

@ -1119,8 +1119,7 @@ static void *hidthread(void *arg)
struct usb_device *usb_dev; struct usb_device *usb_dev;
struct usb_dev_handle *usb_handle; struct usb_dev_handle *usb_handle;
struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg; struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
struct timeval to; struct pollfd pfd = { .events = POLLIN };
fd_set rfds;
usb_dev = hid_device_init(o->devstr); usb_dev = hid_device_init(o->devstr);
if (usb_dev == NULL) { if (usb_dev == NULL) {
@ -1156,42 +1155,31 @@ static void *hidthread(void *arg)
traceusb1(("hidthread: Starting normally on %s!!\n",o->name)); traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
lastrx = 0; lastrx = 0;
// popen // popen
while(!o->stophid) while (!o->stophid) {
{ pfd.fd = o->pttkick;
to.tv_sec = 0; pfd.revents = 0;
to.tv_usec = 50000; // maw sph
FD_ZERO(&rfds); res = ast_poll2(&pfd, 1, 50);
FD_SET(o->pttkick[0],&rfds);
/* ast_select emulates linux behaviour in terms of timeout handling */
res = ast_select(o->pttkick[0] + 1, &rfds, NULL, NULL, &to);
if (res < 0) { if (res < 0) {
ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
usleep(10000); usleep(10000);
continue; continue;
} }
if (FD_ISSET(o->pttkick[0],&rfds)) if (pfd.revents & POLLIN) { {
{
char c; char c;
if (read(o->pttkick[0], &c, 1) < 0) { if (read(o->pttkick[0], &c, 1) < 0) {
ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno)); ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
} }
} }
if(o->wanteeprom) if (o->wanteeprom) {
{
ast_mutex_lock(&o->eepromlock); ast_mutex_lock(&o->eepromlock);
if (o->eepromctl == 1) /* to read */ if (o->eepromctl == 1) { /* to read */
{
/* if CS okay */ /* if CS okay */
if (!get_eeprom(usb_handle,o->eeprom)) if (!get_eeprom(usb_handle, o->eeprom)) {
{ if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC) {
if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC)
{
ast_log(LOG_NOTICE, "UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n", o->name); ast_log(LOG_NOTICE, "UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n", o->name);
} } else {
else
{
o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET]; o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
o->txmixaset = o->eeprom[EEPROM_TXMIXASET]; o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
o->txmixbset = o->eeprom[EEPROM_TXMIXBSET]; o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
@ -1201,15 +1189,12 @@ static void *hidthread(void *arg)
o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ]; o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name); ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
} }
} } else {
else
{
ast_log(LOG_NOTICE, "USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n", o->name); ast_log(LOG_NOTICE, "USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n", o->name);
} }
hid_set_outputs(usb_handle,bufsave); hid_set_outputs(usb_handle,bufsave);
} }
if (o->eepromctl == 2) /* to write */ if (o->eepromctl == 2) { /* to write */
{
put_eeprom(usb_handle,o->eeprom); put_eeprom(usb_handle,o->eeprom);
hid_set_outputs(usb_handle,bufsave); hid_set_outputs(usb_handle,bufsave);
ast_log(LOG_NOTICE, "USB Parameters written to EEPROM on %s\n", o->name); ast_log(LOG_NOTICE, "USB Parameters written to EEPROM on %s\n", o->name);
@ -1220,27 +1205,30 @@ static void *hidthread(void *arg)
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
hid_get_inputs(usb_handle,buf); hid_get_inputs(usb_handle,buf);
keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor); keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
if (keyed != o->rxhidsq) if (keyed != o->rxhidsq) {
{ if (o->debuglevel) {
if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed); printf("chan_usbradio() hidthread: update rxhidsq = %d\n", keyed);
}
o->rxhidsq=keyed; o->rxhidsq=keyed;
} }
/* if change in tx state as controlled by xpmr */ /* if change in tx state as controlled by xpmr */
txtmp = o->pmrChan->txPttOut; txtmp = o->pmrChan->txPttOut;
if (o->lasttx != txtmp) if (o->lasttx != txtmp) {
{
o->pmrChan->txPttHid = o->lasttx = txtmp; o->pmrChan->txPttHid = o->lasttx = txtmp;
if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp); if (o->debuglevel) {
ast_debug(0, "hidthread: tx set to %d\n", txtmp);
}
buf[o->hid_gpio_loc] = 0; buf[o->hid_gpio_loc] = 0;
if (!o->invertptt) if (!o->invertptt) {
{ if (txtmp) {
if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt; buf[o->hid_gpio_loc] = o->hid_io_ptt;
}
} else {
if (!txtmp) {
buf[o->hid_gpio_loc] = o->hid_io_ptt;
} }
else
{
if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
} }
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
memcpy(bufsave, buf, sizeof(buf)); memcpy(bufsave, buf, sizeof(buf));
@ -1249,7 +1237,9 @@ static void *hidthread(void *arg)
time(&o->lasthidtime); time(&o->lasthidtime);
} }
buf[o->hid_gpio_loc] = 0; buf[o->hid_gpio_loc] = 0;
if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt; if (o->invertptt) {
buf[o->hid_gpio_loc] = o->hid_io_ptt;
}
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
hid_set_outputs(usb_handle, buf); hid_set_outputs(usb_handle, buf);
pthread_exit(0); pthread_exit(0);
@ -1452,37 +1442,29 @@ static void *sound_thread(void *arg)
*/ */
read(o->sounddev, ign, sizeof(ign)); read(o->sounddev, ign, sizeof(ign));
for (;;) { for (;;) {
fd_set rfds, wfds; struct pollfd pfd[2] = { { .fd = o->sndcmd[0], .events = POLLIN }, { .fd = o->sounddev } };
int maxfd, res; int res;
FD_ZERO(&rfds); if (o->cursound > -1 && o->sounddev < 0) {
FD_ZERO(&wfds);
FD_SET(o->sndcmd[0], &rfds);
maxfd = o->sndcmd[0]; /* pipe from the main process */
if (o->cursound > -1 && o->sounddev < 0)
setformat(o, O_RDWR); /* need the channel, try to reopen */ setformat(o, O_RDWR); /* need the channel, try to reopen */
else if (o->cursound == -1 && o->owner == NULL) } else if (o->cursound == -1 && o->owner == NULL) {
{
setformat(o, O_CLOSE); /* can close */ setformat(o, O_CLOSE); /* can close */
} }
if (o->sounddev > -1) { if (o->sounddev > -1) {
if (!o->owner) { /* no one owns the audio, so we must drain it */ if (!o->owner) { /* no one owns the audio, so we must drain it */
FD_SET(o->sounddev, &rfds); pfd[1].events = POLLIN;
maxfd = MAX(o->sounddev, maxfd);
} }
if (o->cursound > -1) { if (o->cursound > -1) {
FD_SET(o->sounddev, &wfds); pfd[1].events |= POLLOUT;
maxfd = MAX(o->sounddev, maxfd);
} }
} }
/* ast_select emulates linux behaviour in terms of timeout handling */ res = ast_poll(pfd, o->sounddev > -1 ? 2 : 1, -1);
res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
if (res < 1) { if (res < 1) {
ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); ast_log(LOG_WARNING, "poll failed: %s\n", strerror(errno));
sleep(1); sleep(1);
continue; continue;
} }
if (FD_ISSET(o->sndcmd[0], &rfds)) { if (pfd[0].revents & POLLIN) {
/* read which sound to play from the pipe */ /* read which sound to play from the pipe */
int i, what = -1; int i, what = -1;
@ -1495,16 +1477,19 @@ static void *sound_thread(void *arg)
break; break;
} }
} }
if (sounds[i].ind == -1) if (sounds[i].ind == -1) {
ast_log(LOG_WARNING, "invalid sound index: %d\n", what); ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
} }
}
if (o->sounddev > -1) { if (o->sounddev > -1) {
if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */ if (pfd[1].revents & POLLIN) { /* read and ignore errors */
read(o->sounddev, ign, sizeof(ign)); read(o->sounddev, ign, sizeof(ign));
if (FD_ISSET(o->sounddev, &wfds)) }
if (pfd[1].revents & POLLOUT) {
send_sound(o); send_sound(o);
} }
} }
}
return NULL; /* Never reached */ return NULL; /* Never reached */
} }

@ -387,9 +387,10 @@ static struct fbuf_t *grabber_read(struct video_device *dev, int fps)
*/ */
static void grabber_move(struct video_device *dev, int dx, int dy) static void grabber_move(struct video_device *dev, int dx, int dy)
{ {
if (dev->grabber && dev->grabber->move) if (dev->grabber && dev->grabber->move) {
dev->grabber->move(dev->grabber_data, dx, dy); dev->grabber->move(dev->grabber_data, dx, dy);
} }
}
/* /*
* Map the codec name to the library. If not recognised, use a default. * Map the codec name to the library. If not recognised, use a default.
@ -528,8 +529,7 @@ static int video_out_init(struct video_desc *env)
v->enc->enc_init(v->enc_ctx); v->enc->enc_init(v->enc_ctx);
if (avcodec_open(enc_ctx, v->codec) < 0) { if (avcodec_open(enc_ctx, v->codec) < 0) {
ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n", ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n", codec);
codec);
av_free(enc_ctx); av_free(enc_ctx);
v->enc_ctx = NULL; v->enc_ctx = NULL;
return video_out_uninit(env); return video_out_uninit(env);
@ -873,8 +873,9 @@ static void *video_thread(void *arg)
} }
} }
sdl_setup(env); sdl_setup(env);
if (!ast_strlen_zero(save_display)) if (!ast_strlen_zero(save_display)) {
setenv("DISPLAY", save_display, 1); setenv("DISPLAY", save_display, 1);
}
ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */ ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */
@ -882,8 +883,9 @@ static void *video_thread(void *arg)
ast_log(LOG_WARNING, "cannot open local video source\n"); ast_log(LOG_WARNING, "cannot open local video source\n");
} }
if (env->out.device_num) if (env->out.device_num) {
env->out.devices[env->out.device_primary].status_index |= IS_PRIMARY | IS_SECONDARY; env->out.devices[env->out.device_primary].status_index |= IS_PRIMARY | IS_SECONDARY;
}
/* even if no device is connected, we must call video_out_init, /* even if no device is connected, we must call video_out_init,
* as some of the data structures it initializes are * as some of the data structures it initializes are
@ -900,7 +902,7 @@ static void *video_thread(void *arg)
} }
for (;;) { for (;;) {
struct timeval t = { 0, 50000 }; /* XXX 20 times/sec */ struct timespec t = { 0, 50000000 }; /* XXX 20 times/sec */
struct ast_frame *p, *f; struct ast_frame *p, *f;
struct ast_channel *chan; struct ast_channel *chan;
int fd; int fd;
@ -908,13 +910,14 @@ static void *video_thread(void *arg)
/* determine if video format changed */ /* determine if video format changed */
if (count++ % 10 == 0) { if (count++ % 10 == 0) {
if (env->out.sendvideo && env->out.devices) if (env->out.sendvideo && env->out.devices) {
sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps", snprintf(buf, sizeof(buf), "%s %s %dx%d @@ %dfps %dkbps",
env->out.devices[env->out.device_primary].name, env->codec_name, env->out.devices[env->out.device_primary].name, env->codec_name,
env->enc_in.w, env->enc_in.h, env->enc_in.w, env->enc_in.h,
env->out.fps, env->out.bitrate / 1000); env->out.fps, env->out.bitrate / 1000);
else } else {
sprintf(buf, "hold"); sprintf(buf, "hold");
}
caption = buf; caption = buf;
} }
@ -925,7 +928,7 @@ static void *video_thread(void *arg)
eventhandler(env, caption); eventhandler(env, caption);
/* sleep for a while */ /* sleep for a while */
ast_select(0, NULL, NULL, NULL, &t); nanosleep(&t, NULL);
if (env->in) { if (env->in) {
struct video_dec_desc *v = env->in; struct video_dec_desc *v = env->in;

61328
configure vendored

File diff suppressed because it is too large Load Diff

@ -60,6 +60,7 @@ case "${host_os}" in
;; ;;
darwin*) darwin*)
AC_DEFINE([AST_POLL_COMPAT], 1, [Define to 1 if internal poll should be used.]) AC_DEFINE([AST_POLL_COMPAT], 1, [Define to 1 if internal poll should be used.])
AC_DEFINE([_DARWIN_UNLIMITED_SELECT], 1, [Define to 1 if running on Darwin.])
;; ;;
*) *)
AC_PREFIX_DEFAULT([/usr]) AC_PREFIX_DEFAULT([/usr])
@ -466,7 +467,7 @@ AC_FUNC_STRNLEN
AC_FUNC_STRTOD AC_FUNC_STRTOD
AC_FUNC_UTIME_NULL AC_FUNC_UTIME_NULL
AC_FUNC_VPRINTF AC_FUNC_VPRINTF
AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob htonll ioperm inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap ntohll newlocale putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv utime vasprintf getpeereid sysctl swapctl]) AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob htonll ioperm inet_ntoa isascii memchr memmove memset mkdir munmap ntohll newlocale ppoll putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv utime vasprintf getpeereid sysctl swapctl])
# NOTE: we use AC_CHECK_LIB to get -lm into the arguments for later checks, # NOTE: we use AC_CHECK_LIB to get -lm into the arguments for later checks,
# so that AC_CHECK_FUNCS can detect functions in that library. # so that AC_CHECK_FUNCS can detect functions in that library.
@ -741,6 +742,48 @@ AC_RUN_IFELSE(
AC_MSG_RESULT(unknown) AC_MSG_RESULT(unknown)
) )
AC_MSG_CHECKING(if we can increase the maximum select-able file descriptor)
AC_RUN_IFELSE(
AC_LANG_PROGRAM([
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
], [[
struct rlimit rlim = { FD_SETSIZE * 2, FD_SETSIZE * 2 };
int fd0, fd1;
struct timeval tv = { 0, };
struct ast_fdset { long fds_bits[[1024]]; } fds = { { 0, } };
if (setrlimit(RLIMIT_NOFILE, &rlim)) { exit(1); }
if ((fd0 = open("/dev/null", O_RDONLY)) < 0) { exit(1); }
if (dup2(fd0, (fd1 = FD_SETSIZE + 1)) < 0) { exit(1); }
FD_SET(fd0, (fd_set *) &fds);
FD_SET(fd1, (fd_set *) &fds);
if (select(FD_SETSIZE + 2, (fd_set *) &fds, NULL, NULL, &tv) < 0) { exit(1); }
exit(0)]]),
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_VARIABLE_FDSET], 1, [Define to 1 if your system can support larger than default select bitmasks.]),
AC_MSG_RESULT(no),
AC_MSG_RESULT(cross-compile)
)
if test "${ac_cv_have_variable_fdset}x" = "0x"; then
AC_RUN_IFELSE(
AC_LANG_PROGRAM([
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
], [if (getuid() != 0) { exit(1); }]),
AC_DEFINE([CONFIGURE_RAN_AS_ROOT], 1, [Some configure tests will unexpectedly fail if configure is run by a non-root user. These may be able to be tested at runtime.]))
fi
AST_GCC_ATTRIBUTE(pure) AST_GCC_ATTRIBUTE(pure)
AST_GCC_ATTRIBUTE(malloc) AST_GCC_ATTRIBUTE(malloc)
AST_GCC_ATTRIBUTE(const) AST_GCC_ATTRIBUTE(const)

@ -17,6 +17,10 @@
/* Define to 1 if the `closedir' function returns void instead of `int'. */ /* Define to 1 if the `closedir' function returns void instead of `int'. */
#undef CLOSEDIR_VOID #undef CLOSEDIR_VOID
/* Some configure tests will unexpectedly fail if configure is run by a
non-root user. These may be able to be tested at runtime. */
#undef CONFIGURE_RAN_AS_ROOT
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems. systems. This function is required for `alloca.c' support on those systems.
*/ */
@ -381,9 +385,6 @@
/* Define to 1 if your system defines the locale_t type in xlocale.h */ /* Define to 1 if your system defines the locale_t type in xlocale.h */
#undef HAVE_LOCALE_T_IN_XLOCALE_H #undef HAVE_LOCALE_T_IN_XLOCALE_H
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define to 1 if you have the `log' function. */ /* Define to 1 if you have the `log' function. */
#undef HAVE_LOG #undef HAVE_LOG
@ -538,6 +539,9 @@
/* Define to 1 if you have the `powl' function. */ /* Define to 1 if you have the `powl' function. */
#undef HAVE_POWL #undef HAVE_POWL
/* Define to 1 if you have the `ppoll' function. */
#undef HAVE_PPOLL
/* Define to 1 if you have the ISDN PRI library. */ /* Define to 1 if you have the ISDN PRI library. */
#undef HAVE_PRI #undef HAVE_PRI
@ -803,7 +807,7 @@
/* Define to 1 if you have the `strtoq' function. */ /* Define to 1 if you have the `strtoq' function. */
#undef HAVE_STRTOQ #undef HAVE_STRTOQ
/* Define to 1 if `st_blksize' is a member of `struct stat'. */ /* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE #undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if you have the mISDN Supplemental Services library. */ /* Define to 1 if you have the mISDN Supplemental Services library. */
@ -956,6 +960,10 @@
/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */ /* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL #undef HAVE_UTIME_NULL
/* Define to 1 if your system can support larger than default select bitmasks.
*/
#undef HAVE_VARIABLE_FDSET
/* Define to 1 if you have the `vasprintf' function. */ /* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF #undef HAVE_VASPRINTF
@ -1074,12 +1082,12 @@
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME #undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */ /* Define to the version of this package. */
#undef PACKAGE_VERSION #undef PACKAGE_VERSION
/* Define to 1 if the C compiler supports function prototypes. */
#undef PROTOTYPES
/* Define to necessary symbol if this constant uses a non-standard name on /* Define to necessary symbol if this constant uses a non-standard name on
your system. */ your system. */
#undef PTHREAD_CREATE_JOINABLE #undef PTHREAD_CREATE_JOINABLE
@ -1099,6 +1107,11 @@
/* Define to the type of arg 5 for `select'. */ /* Define to the type of arg 5 for `select'. */
#undef SELECT_TYPE_ARG5 #undef SELECT_TYPE_ARG5
/* Define to 1 if the `setvbuf' function takes the buffering type as its
second argument and the buffer pointer as the third, as on System V before
release 3. */
#undef SETVBUF_REVERSED
/* The size of `char *', as computed by sizeof. */ /* The size of `char *', as computed by sizeof. */
#undef SIZEOF_CHAR_P #undef SIZEOF_CHAR_P
@ -1128,31 +1141,24 @@
/* Define to 1 if your <sys/time.h> declares `struct tm'. */ /* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME #undef TM_IN_SYS_TIME
/* Enable extensions on AIX 3, Interix. */ /* Define to 1 if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE #ifndef _ALL_SOURCE
# undef _ALL_SOURCE # undef _ALL_SOURCE
#endif #endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Define to 1 if running on Darwin. */
#undef _DARWIN_UNLIMITED_SELECT
/* Number of bits in a file offset, on hosts where this is settable. */ /* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS #undef _FILE_OFFSET_BITS
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
#undef _LARGEFILE_SOURCE #undef _LARGEFILE_SOURCE
@ -1169,6 +1175,20 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */ /* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE #undef _POSIX_SOURCE
/* Enable extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Define like PROTOTYPES; this can be used by system headers. */
#undef __PROTOTYPES
/* Define to empty if `const' does not conform to ANSI C. */ /* Define to empty if `const' does not conform to ANSI C. */
#undef const #undef const

@ -2232,44 +2232,6 @@ static inline void timersub(struct timeval *tvend, struct timeval *tvstart, stru
} }
#endif #endif
/*!
* \brief 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
* \details
* 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
*/
static inline 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, tvp);
#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 select(nfds, rfds, wfds, efds, NULL);
#endif
}
/*! \brief Retrieves the current T38 state of a channel */ /*! \brief Retrieves the current T38 state of a channel */
static inline enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan) static inline enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
{ {

@ -79,6 +79,8 @@
#ifndef __AST_POLL_COMPAT_H #ifndef __AST_POLL_COMPAT_H
#define __AST_POLL_COMPAT_H #define __AST_POLL_COMPAT_H
#include "asterisk/select.h"
#ifndef AST_POLL_COMPAT #ifndef AST_POLL_COMPAT
#include <sys/poll.h> #include <sys/poll.h>
@ -114,4 +116,24 @@ int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout);
#endif /* AST_POLL_COMPAT */ #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);
/*!
* \brief Shortcut for conversion of FD_ISSET to poll(2)-based
*/
static inline int ast_poll_fd_index(struct pollfd *haystack, int nfds, int needle)
{
int i;
for (i = 0; i < nfds; i++) {
if (haystack[i].fd == needle) {
return i;
}
}
return -1;
}
#endif /* __AST_POLL_COMPAT_H */ #endif /* __AST_POLL_COMPAT_H */

@ -0,0 +1,110 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2010, Digium, Inc.
*
* Tilghman Lesher <tlesher AT digium DOT com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!\file
* \brief Bitfield expansions for ast_select
*/
#ifndef __AST_SELECT_H
#define __AST_SELECT_H
#include <sys/select.h>
#include <errno.h>
#include "asterisk/utils.h"
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned int ast_FD_SETSIZE;
#if !defined(HAVE_VARIABLE_FDSET) && defined(CONFIGURE_RAN_AS_ROOT)
#define ast_fdset fd_set
#else
typedef struct {
long fds_bits[4096 / sizeof(long)]; /* 32768 bits */
} ast_fdset;
#undef FD_ZERO
#define FD_ZERO(a) \
do { \
long *bytes = (long *) a; \
int i; \
for (i = 0; i < sizeof(*(a)) / sizeof(long); i++) { \
bytes[i] = 0; \
} \
} while (0)
#undef FD_SET
#define FD_SET(fd, fds) \
do { \
long *bytes = (long *) fds; \
if (fd / sizeof(*bytes) + ((fd + 1) % sizeof(*bytes) ? 1 : 0) < sizeof(*(fds))) { \
bytes[fd / (sizeof(*bytes))] |= 1L << (fd % sizeof(*bytes)); \
} else { \
ast_log(LOG_ERROR, "FD %d exceeds the maximum size of ast_fdset!\n", fd); \
} \
} while (0)
#endif /* HAVE_VARIABLE_FDSET */
/*! \brief 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
*/
static inline int ast_select(int nfds, ast_fdset *rfds, ast_fdset *wfds, ast_fdset *efds, struct timeval *tvp)
{
#ifdef __linux__
ast_assert((unsigned int) nfds <= ast_FD_SETSIZE);
return select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, tvp);
#else
int save_errno = 0;
ast_assert((unsigned int) nfds <= ast_FD_SETSIZE);
if (tvp) {
struct timeval tv, tvstart, tvend, tvlen;
int res;
tv = *tvp;
gettimeofday(&tvstart, NULL);
res = select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, tvp);
save_errno = errno;
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;
}
errno = save_errno;
return res;
}
else
return select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, NULL);
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* __AST_SELECT_H */

@ -1,7 +1,7 @@
/* /*
* Asterisk -- An open source telephony toolkit. * Asterisk -- An open source telephony toolkit.
* *
* Copyright (C) 1999 - 2008, Digium, Inc. * Copyright (C) 1999 - 2010, Digium, Inc.
* *
* Mark Spencer <markster@digium.com> * Mark Spencer <markster@digium.com>
* *
@ -272,6 +272,8 @@ static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0"; static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl"; static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
extern unsigned int ast_FD_SETSIZE;
static char *_argv[256]; static char *_argv[256];
static int shuttingdown; static int shuttingdown;
static int restartnow; static int restartnow;
@ -3168,6 +3170,7 @@ int main(int argc, char *argv[])
const char *runuser = NULL, *rungroup = NULL; const char *runuser = NULL, *rungroup = NULL;
char *remotesock = NULL; char *remotesock = NULL;
int moduleresult; /*!< Result from the module load subsystem */ int moduleresult; /*!< Result from the module load subsystem */
struct rlimit l;
/* Remember original args for restart */ /* Remember original args for restart */
if (argc > ARRAY_LEN(_argv) - 1) { if (argc > ARRAY_LEN(_argv) - 1) {
@ -3352,7 +3355,6 @@ int main(int argc, char *argv[])
} }
if (ast_opt_dump_core) { if (ast_opt_dump_core) {
struct rlimit l;
memset(&l, 0, sizeof(l)); memset(&l, 0, sizeof(l));
l.rlim_cur = RLIM_INFINITY; l.rlim_cur = RLIM_INFINITY;
l.rlim_max = RLIM_INFINITY; l.rlim_max = RLIM_INFINITY;
@ -3361,6 +3363,44 @@ int main(int argc, char *argv[])
} }
} }
if (getrlimit(RLIMIT_NOFILE, &l)) {
ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
}
#if !defined(CONFIGURE_RAN_AS_ROOT)
/* Check if select(2) will run with more file descriptors */
do {
int fd, fd2;
ast_fdset readers;
struct timeval tv = { 0, };
if (l.rlim_cur <= FD_SETSIZE) {
/* The limit of select()able FDs is irrelevant, because we'll never
* open one that high. */
break;
}
if (!(fd = open("/dev/null", O_RDONLY))) {
ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
break; /* XXX Should we exit() here? XXX */
}
fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
if (dup2(fd, fd2)) {
ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
break;
}
FD_ZERO(&readers);
FD_SET(fd2, &readers);
if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
}
} while (0);
#elif defined(HAVE_VARIABLE_FDSET)
ast_FD_SETSIZE = l.rlim_cur;
#endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP)) if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
rungroup = ast_config_AST_RUN_GROUP; rungroup = ast_config_AST_RUN_GROUP;
if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER)) if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))

@ -438,7 +438,7 @@ static const struct ast_datastore_info dial_features_info = {
static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot); static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
static void parkinglot_unref(struct ast_parkinglot *parkinglot); static void parkinglot_unref(struct ast_parkinglot *parkinglot);
static void parkinglot_destroy(void *obj); static void parkinglot_destroy(void *obj);
int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max); int manage_parkinglot(struct ast_parkinglot *curlot, struct pollfd **pfds, int *nfds, int *fs);
struct ast_parkinglot *find_parkinglot(const char *name); struct ast_parkinglot *find_parkinglot(const char *name);
static struct ast_parkinglot *create_parkinglot(const char *name); static struct ast_parkinglot *create_parkinglot(const char *name);
static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot); static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
@ -3603,9 +3603,10 @@ static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_
} }
/*! \brief Run management on parkinglots, called once per parkinglot */ /*! \brief Run management on parkinglots, called once per parkinglot */
int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *ms, int *max) int manage_parkinglot(struct ast_parkinglot *curlot, struct pollfd **pfds, int *nfds, int *ms)
{ {
struct pollfd *new_fds = NULL;
int new_nfds = 0;
struct parkeduser *pu; struct parkeduser *pu;
int res = 0; int res = 0;
char parkingslot[AST_MAX_EXTENSION]; char parkingslot[AST_MAX_EXTENSION];
@ -3628,12 +3629,12 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
/* Get chan, exten from derived kludge */ /* Get chan, exten from derived kludge */
if (pu->peername[0]) { if (pu->peername[0]) {
char *peername = ast_strdupa(pu->peername); char *peername = ast_strdupa(pu->peername);
char *cp = strrchr(peername, '-'); char *dash = strrchr(peername, '-');
char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */ char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
int i; int i;
if (cp) { if (dash) {
*cp = 0; *dash = '\0';
} }
peername_flat = ast_strdupa(peername); peername_flat = ast_strdupa(peername);
@ -3712,14 +3713,33 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
} else { /* still within parking time, process descriptors */ } else { /* still within parking time, process descriptors */
for (x = 0; x < AST_MAX_FDS; x++) { for (x = 0; x < AST_MAX_FDS; x++) {
struct ast_frame *f; struct ast_frame *f;
int y;
if (chan->fds[x] == -1) {
continue; /* nothing on this descriptor */
}
if ((chan->fds[x] == -1) || (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds))) for (y = 0; y < *nfds; y++) {
if ((*pfds[y]).fd == chan->fds[x]) {
/* Found poll record! */
break;
}
}
if (y == *nfds) {
/* Not found */
continue; continue;
}
if (FD_ISSET(chan->fds[x], efds)) if (!((*pfds[y]).revents & (POLLIN | POLLERR))) {
/* Next x */
continue;
}
if ((*pfds[y]).revents & POLLERR) {
ast_set_flag(chan, AST_FLAG_EXCEPTION); ast_set_flag(chan, AST_FLAG_EXCEPTION);
else } else {
ast_clear_flag(chan, AST_FLAG_EXCEPTION); ast_clear_flag(chan, AST_FLAG_EXCEPTION);
}
chan->fdno = x; chan->fdno = x;
/* See if they need servicing */ /* See if they need servicing */
@ -3762,20 +3782,30 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
if (x >= AST_MAX_FDS) { if (x >= AST_MAX_FDS) {
std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */ std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
if (chan->fds[x] > -1) { if (chan->fds[x] > -1) {
FD_SET(chan->fds[x], nrfds); void *tmp = ast_realloc(new_fds, (new_nfds + 1) * sizeof(*new_fds));
FD_SET(chan->fds[x], nefds); if (!tmp) {
if (chan->fds[x] > *max) continue;
*max = chan->fds[x]; }
new_fds = tmp;
new_fds[new_nfds].fd = chan->fds[x];
new_fds[new_nfds].events = POLLIN | POLLERR;
new_fds[new_nfds].revents = 0;
new_nfds++;
} }
} }
/* Keep track of our shortest wait */ /* Keep track of our shortest wait */
if (tms < *ms || *ms < 0) if (tms < *ms || *ms < 0) {
*ms = tms; *ms = tms;
} }
} }
} }
}
AST_LIST_TRAVERSE_SAFE_END; AST_LIST_TRAVERSE_SAFE_END;
AST_LIST_UNLOCK(&curlot->parkings); AST_LIST_UNLOCK(&curlot->parkings);
ast_free(*pfds);
*pfds = new_fds;
*nfds = new_nfds;
return res; return res;
} }
@ -3789,35 +3819,26 @@ std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
*/ */
static void *do_parking_thread(void *ignore) static void *do_parking_thread(void *ignore)
{ {
fd_set rfds, efds; /* results from previous select, to be preserved across loops. */ struct pollfd *pfds = NULL;
fd_set nrfds, nefds; /* args for the next select */ int nfds = 0;
FD_ZERO(&rfds);
FD_ZERO(&efds);
for (;;) { for (;;) {
int res = 0;
int ms = -1; /* select timeout, uninitialized */
int max = -1; /* max fd, none there yet */
struct ao2_iterator iter; struct ao2_iterator iter;
struct ast_parkinglot *curlot; struct ast_parkinglot *curlot;
FD_ZERO(&nrfds); int ms = -1; /* poll2 timeout, uninitialized */
FD_ZERO(&nefds);
iter = ao2_iterator_init(parkinglots, 0); iter = ao2_iterator_init(parkinglots, 0);
while ((curlot = ao2_iterator_next(&iter))) { while ((curlot = ao2_iterator_next(&iter))) {
res = manage_parkinglot(curlot, &rfds, &efds, &nrfds, &nefds, &ms, &max); manage_parkinglot(curlot, &pfds, &nfds, &ms);
ao2_ref(curlot, -1); ao2_ref(curlot, -1);
} }
ao2_iterator_destroy(&iter);
rfds = nrfds;
efds = nefds;
{
struct timeval wait = ast_samp2tv(ms, 1000);
/* Wait for something to happen */ /* Wait for something to happen */
ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &wait : NULL); ast_poll(pfds, nfds, ms);
}
pthread_testcancel(); pthread_testcancel();
} }
/* If this WERE reached, we'd need to free(pfds) */
return NULL; /* Never reached */ return NULL; /* Never reached */
} }

@ -78,11 +78,12 @@
#include <sys/time.h> /* time definitions */ #include <sys/time.h> /* time definitions */
#include <assert.h> /* assertion macros */ #include <assert.h> /* assertion macros */
#include <string.h> /* string functions */ #include <string.h> /* string functions */
#include <errno.h>
#include "asterisk/utils.h" /* this package */ #include "asterisk/utils.h" /* this package */
#include "asterisk/poll-compat.h" /* this package */ #include "asterisk/poll-compat.h" /* this package */
#ifdef AST_POLL_COMPAT unsigned int ast_FD_SETSIZE = FD_SETSIZE;
#ifndef MAX #ifndef MAX
#define MAX(a,b) a > b ? a : b #define MAX(a,b) a > b ? a : b
@ -92,35 +93,24 @@
Private Functions Private Functions
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
static int map_poll_spec #if defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL)
#if __STDC__ > 0 static int map_poll_spec(struct pollfd *pArray, unsigned long n_fds,
(struct pollfd *pArray, ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
unsigned long n_fds,
fd_set *pReadSet,
fd_set *pWriteSet,
fd_set *pExceptSet)
#else
(pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
struct pollfd *pArray;
unsigned long n_fds;
fd_set *pReadSet;
fd_set *pWriteSet;
fd_set *pExceptSet;
#endif
{ {
register unsigned long i; /* loop control */ register unsigned long i; /* loop control */
register struct pollfd *pCur; /* current array element */ register struct pollfd *pCur; /* current array element */
register int max_fd = -1; /* return value */ register int max_fd = -1; /* return value */
/*!\note /*
* Map the poll() structures into the file descriptor sets required * Map the poll() structures into the file descriptor sets required
* by select(). * by select().
*/ */
for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) { for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
/* Skip any bad FDs in the array. */ /* Skip any bad FDs in the array. */
if (pCur->fd < 0) if (pCur->fd < 0) {
continue; continue;
}
if (pCur->events & POLLIN) { if (pCur->events & POLLIN) {
/* "Input Ready" notification desired. */ /* "Input Ready" notification desired. */
@ -145,34 +135,28 @@ static int map_poll_spec
return max_fd; return max_fd;
} }
static struct timeval *map_timeout #ifdef AST_POLL_COMPAT
#if __STDC__ > 0 static struct timeval *map_timeout(int poll_timeout, struct timeval *pSelTimeout)
(int poll_timeout, struct timeval *pSelTimeout)
#else
(poll_timeout, pSelTimeout)
int poll_timeout;
struct timeval *pSelTimeout;
#endif
{ {
struct timeval *pResult; struct timeval *pResult;
/*!\note /*
* Map the poll() timeout value into a select() timeout. The possible Map the poll() timeout value into a select() timeout. The possible
* values of the poll() timeout value, and their meanings, are: values of the poll() timeout value, and their meanings, are:
*
* VALUE MEANING VALUE MEANING
*
* -1 wait indefinitely (until signal occurs) -1 wait indefinitely (until signal occurs)
* 0 return immediately, don't block 0 return immediately, don't block
* >0 wait specified number of milliseconds >0 wait specified number of milliseconds
*
* select() uses a "struct timeval", which specifies the timeout in select() uses a "struct timeval", which specifies the timeout in
* seconds and microseconds, so the milliseconds value has to be mapped seconds and microseconds, so the milliseconds value has to be mapped
* accordingly. accordingly.
*/ */
assert(pSelTimeout != (struct timeval *) NULL); assert(pSelTimeout != NULL);
switch (poll_timeout) { switch (poll_timeout) {
case -1: case -1:
@ -203,22 +187,10 @@ static struct timeval *map_timeout
return pResult; return pResult;
} }
#endif /* AST_POLL_COMPAT */
static void map_select_results static void map_select_results(struct pollfd *pArray, unsigned long n_fds,
#if __STDC__ > 0 ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
(struct pollfd *pArray,
unsigned long n_fds,
fd_set *pReadSet,
fd_set *pWriteSet,
fd_set *pExceptSet)
#else
(pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
struct pollfd *pArray;
unsigned long n_fds;
fd_set *pReadSet;
fd_set *pWriteSet;
fd_set *pExceptSet;
#endif
{ {
register unsigned long i; /* loop control */ register unsigned long i; /* loop control */
register struct pollfd *pCur; /* current array element */ register struct pollfd *pCur; /* current array element */
@ -231,35 +203,36 @@ static void map_select_results
} }
/* Exception events take priority over input events. */ /* Exception events take priority over input events. */
pCur->revents = 0; pCur->revents = 0;
if (FD_ISSET (pCur->fd, pExceptSet)) { if (FD_ISSET(pCur->fd, (fd_set *) pExceptSet)) {
pCur->revents |= POLLPRI; pCur->revents |= POLLPRI;
} else if (FD_ISSET (pCur->fd, pReadSet)) { } else if (FD_ISSET(pCur->fd, (fd_set *) pReadSet)) {
pCur->revents |= POLLIN; pCur->revents |= POLLIN;
} }
if (FD_ISSET (pCur->fd, pWriteSet)) { if (FD_ISSET(pCur->fd, (fd_set *) pWriteSet)) {
pCur->revents |= POLLOUT; pCur->revents |= POLLOUT;
} }
} }
return; return;
} }
#endif /* defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL) */
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Public Functions Public Functions
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifdef AST_POLL_COMPAT
int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout) int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
{ {
fd_set read_descs; /* input file descs */ ast_fdset read_descs; /* input file descs */
fd_set write_descs; /* output file descs */ ast_fdset write_descs; /* output file descs */
fd_set except_descs; /* exception descs */ ast_fdset except_descs; /* exception descs */
struct timeval stime; /* select() timeout value */ struct timeval stime; /* select() timeout value */
int ready_descriptors; /* function result */ int ready_descriptors; /* function result */
int max_fd = 0; /* maximum fd value */ int max_fd = 0; /* maximum fd value */
struct timeval *pTimeout; /* actually passed */ struct timeval *pTimeout; /* actually passed */
int save_errno;
FD_ZERO(&read_descs); FD_ZERO(&read_descs);
FD_ZERO(&write_descs); FD_ZERO(&write_descs);
@ -273,17 +246,58 @@ int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
} }
/* Map the poll() timeout value in the select() timeout structure. */ /* Map the poll() timeout value in the select() timeout structure. */
pTimeout = map_timeout (timeout, &stime); pTimeout = map_timeout (timeout, &stime);
/* Make the select() call. */ /* Make the select() call. */
ready_descriptors = select(max_fd + 1, &read_descs, &write_descs,
ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs,
&except_descs, pTimeout); &except_descs, pTimeout);
save_errno = errno;
if (ready_descriptors >= 0) {
map_select_results (pArray, n_fds,
&read_descs, &write_descs, &except_descs);
}
errno = save_errno;
return ready_descriptors;
}
#endif /* AST_POLL_COMPAT */
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
{
#ifdef HAVE_PPOLL
struct timeval start = ast_tvnow();
struct timespec ts = { tv ? tv->tv_sec : 0, tv ? tv->tv_usec * 1000 : 0 };
int res = ppoll(pArray, n_fds, tv ? &ts : NULL, NULL);
struct timeval after = ast_tvnow();
if (res > 0 && tv && ast_tvdiff_ms(ast_tvadd(*tv, start), after) > 0) {
*tv = ast_tvsub(*tv, ast_tvsub(after, start));
} else if (res > 0 && tv) {
*tv = ast_tv(0, 0);
}
return res;
#else
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) { if (ready_descriptors >= 0) {
map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs); map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs);
} }
return ready_descriptors; return ready_descriptors;
#endif
} }
#endif /* AST_POLL_COMPAT */

@ -397,8 +397,7 @@ int ast_stun_request(int s, struct sockaddr_in *dst,
for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */ for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */
/* send request, possibly wait for reply */ /* send request, possibly wait for reply */
unsigned char reply_buf[1024]; unsigned char reply_buf[1024];
fd_set rfds; struct pollfd pfds = { .fd = s, .events = POLLIN };
struct timeval to = { 3, 0 }; /* timeout, make it configurable */
struct sockaddr_in src; struct sockaddr_in src;
socklen_t srclen; socklen_t srclen;
@ -410,9 +409,7 @@ int ast_stun_request(int s, struct sockaddr_in *dst,
} }
if (answer == NULL) if (answer == NULL)
break; break;
FD_ZERO(&rfds); res = ast_poll(&pfds, 1, 3000);
FD_SET(s, &rfds);
res = ast_select(s + 1, &rfds, NULL, NULL, &to);
if (res <= 0) /* timeout or error */ if (res <= 0) /* timeout or error */
continue; continue;
memset(&src, 0, sizeof(src)); memset(&src, 0, sizeof(src));

@ -113,9 +113,9 @@ const char *ais_err2str(SaAisErrorT error)
static void *dispatch_thread_handler(void *data) static void *dispatch_thread_handler(void *data)
{ {
SaSelectionObjectT clm_fd, evt_fd, max_fd; SaSelectionObjectT clm_fd, evt_fd;
int res; int res;
fd_set read_fds; struct pollfd pfd[2] = { { .events = POLLIN, }, { .events = POLLIN, } };
SaAisErrorT ais_res; SaAisErrorT ais_res;
ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd); ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd);
@ -132,25 +132,27 @@ static void *dispatch_thread_handler(void *data)
return NULL; return NULL;
} }
max_fd = clm_fd > evt_fd ? clm_fd : evt_fd; pfd[0].fd = clm_fd;
pfd[1].fd = evt_fd;
while (!dispatch_thread.stop) { while (!dispatch_thread.stop) {
FD_ZERO(&read_fds); pfd[0].revents = 0;
FD_SET(clm_fd, &read_fds); pfd[1].revents = 0;
FD_SET(evt_fd, &read_fds);
res = ast_select(max_fd + 1, &read_fds, NULL, NULL, NULL); res = ast_poll(pfd, 2, -1);
if (res == -1 && errno != EINTR && errno != EAGAIN) { if (res == -1 && errno != EINTR && errno != EAGAIN) {
ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, " ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, "
"and the module will no longer operate.\n", strerror(errno)); "and the module will no longer operate.\n", strerror(errno));
break; break;
} }
if (FD_ISSET(clm_fd, &read_fds)) if (pfd[0].revents & POLLIN) {
saClmDispatch(clm_handle, SA_DISPATCH_ALL); saClmDispatch(clm_handle, SA_DISPATCH_ALL);
if (FD_ISSET(evt_fd, &read_fds)) }
if (pfd[1].revents & POLLIN) {
saEvtDispatch(evt_handle, SA_DISPATCH_ALL); saEvtDispatch(evt_handle, SA_DISPATCH_ALL);
} }
}
return NULL; return NULL;
} }

@ -1283,38 +1283,27 @@ static int aji_tls_handshake(struct aji_client *client)
*/ */
static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout) static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout)
{ {
int sock; struct pollfd pfd = { .events = POLLIN };
fd_set fds;
struct timeval tv, *tvptr = NULL;
int len, res; int len, res;
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
if (aji_is_secure(client)) { if (aji_is_secure(client)) {
sock = SSL_get_fd(client->ssl_session); pfd.fd = SSL_get_fd(client->ssl_session);
if (sock < 0) { if (pfd.fd < 0) {
return -1; return -1;
} }
} else } else
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
sock = iks_fd(client->p); pfd.fd = iks_fd(client->p);
memset(&tv, 0, sizeof(struct timeval));
FD_ZERO(&fds);
FD_SET(sock, &fds);
tv.tv_sec = timeout;
/* NULL value for tvptr makes ast_select wait indefinitely */
tvptr = (timeout != -1) ? &tv : NULL;
/* ast_select emulates linux behaviour in terms of timeout handling */ res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1);
res = ast_select(sock + 1, &fds, NULL, NULL, tvptr);
if (res > 0) { if (res > 0) {
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
if (aji_is_secure(client)) { if (aji_is_secure(client)) {
len = SSL_read(client->ssl_session, buffer, buf_len); len = SSL_read(client->ssl_session, buffer, buf_len);
} else } else
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
len = recv(sock, buffer, buf_len, 0); len = recv(pfd.fd, buffer, buf_len, 0);
if (len > 0) { if (len > 0) {
return len; return len;

@ -703,8 +703,7 @@ static void *do_pktccops(void *data)
int res, nfds, len; int res, nfds, len;
struct copsmsg *recmsg, *sendmsg; struct copsmsg *recmsg, *sendmsg;
struct copsmsg recmsgb, sendmsgb; struct copsmsg recmsgb, sendmsgb;
fd_set rfds; struct pollfd *pfds = NULL, *tmp;
struct timeval tv;
struct pktcobj *pobject; struct pktcobj *pobject;
struct cops_cmts *cmts; struct cops_cmts *cmts;
struct cops_gate *gate; struct cops_gate *gate;
@ -719,9 +718,8 @@ static void *do_pktccops(void *data)
ast_debug(3, "COPS: thread started\n"); ast_debug(3, "COPS: thread started\n");
for (;;) { for (;;) {
tv.tv_sec = 1; ast_free(pfds);
tv.tv_usec = 0; pfds = NULL;
FD_ZERO(&rfds);
nfds = 0; nfds = 0;
AST_LIST_LOCK(&cmts_list); AST_LIST_LOCK(&cmts_list);
AST_LIST_TRAVERSE(&cmts_list, cmts, list) { AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
@ -735,15 +733,27 @@ static void *do_pktccops(void *data)
} }
} }
if (cmts->sfd > 0) { if (cmts->sfd > 0) {
FD_SET(cmts->sfd, &rfds); if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
if (cmts->sfd > nfds) nfds = cmts->sfd; continue;
}
pfds = tmp;
pfds[nfds].fd = cmts->sfd;
pfds[nfds].events = POLLIN;
pfds[nfds].revents = 0;
nfds++;
} else { } else {
cmts->sfd = cops_connect(cmts->host, cmts->port); cmts->sfd = cops_connect(cmts->host, cmts->port);
if (cmts->sfd > 0) { if (cmts->sfd > 0) {
cmts->state = 1; cmts->state = 1;
if (cmts->sfd > 0) { if (cmts->sfd > 0) {
FD_SET(cmts->sfd, &rfds); if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
if (cmts->sfd > nfds) nfds = cmts->sfd; continue;
}
pfds = tmp;
pfds[nfds].fd = cmts->sfd;
pfds[nfds].events = POLLIN;
pfds[nfds].revents = 0;
nfds++;
} }
} }
} }
@ -781,10 +791,11 @@ static void *do_pktccops(void *data)
if (pktcreload == 2) { if (pktcreload == 2) {
pktcreload = 0; pktcreload = 0;
} }
if ((res = select(nfds + 1, &rfds, NULL, NULL, &tv))) { if ((res = ast_poll(pfds, nfds, 1000))) {
AST_LIST_LOCK(&cmts_list); AST_LIST_LOCK(&cmts_list);
AST_LIST_TRAVERSE(&cmts_list, cmts, list) { AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
if (FD_ISSET(cmts->sfd, &rfds)) { int idx;
if ((idx = ast_poll_fd_index(pfds, nfds, cmts->sfd)) > -1 && (pfds[idx].revents & POLLIN)) {
len = cops_getmsg(cmts->sfd, recmsg); len = cops_getmsg(cmts->sfd, recmsg);
if (len > 0) { if (len > 0) {
ast_debug(3, "COPS: got from %s:\n Header: versflag=0x%.2x opcode=%i clienttype=0x%.4x msglength=%i\n", ast_debug(3, "COPS: got from %s:\n Header: versflag=0x%.2x opcode=%i clienttype=0x%.4x msglength=%i\n",

@ -0,0 +1,253 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2010, Digium, Inc.
*
* Tilghman Lesher <tlesher AT digium DOT com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief Poll Tests
*
* \author\verbatim Tilghman Lesher <tlesher AT digium DOT com> \endverbatim
*
* Verify that the various poll implementations work as desired (ast_poll, ast_poll2)
* \ingroup tests
*/
/*** MODULEINFO
<depend>TEST_FRAMEWORK</depend>
***/
#include "asterisk.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/test.h"
#include "asterisk/poll-compat.h"
#ifndef HAVE_SBIN_LAUNCHD
static void *failsafe_cancel(void *vparent)
{
pthread_t parent = (pthread_t) (long) vparent;
sleep(1);
pthread_testcancel();
pthread_kill(parent, SIGURG);
sleep(1);
pthread_testcancel();
pthread_kill(parent, SIGURG);
sleep(1);
pthread_testcancel();
pthread_kill(parent, SIGURG);
pthread_exit(NULL);
}
#define RESET for (i = 0; i < 4; i++) { pfd[i].revents = 0; }
AST_TEST_DEFINE(poll_test)
{
#define FDNO 3
int fd[2], res = AST_TEST_PASS, i, res2;
int rdblocker[2];
#if FDNO > 3
int wrblocker[2], consec_interrupt = 0;
#endif
struct pollfd pfd[4] = { { .events = POLLOUT, }, { .events = POLLIN, }, { .events = POLLIN }, { .events = POLLOUT } };
pthread_t failsafe_tid;
struct timeval tv = { 0, 0 };
#if FDNO > 3
char garbage[256] =
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/";
#endif
switch (cmd) {
case TEST_INIT:
info->name = "poll_test";
info->category = "main/poll/";
info->summary = "unit test for the ast_poll() API";
info->description =
"Verifies behavior for the ast_poll() API call\n";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
ast_test_status_update(test, "Creating handle that should NEVER block on write\n");
if ((fd[0] = open("/dev/null", O_WRONLY)) < 0) {
ast_test_status_update(test, "Unable to open a writable handle to /dev/null: %s\n", strerror(errno));
return AST_TEST_FAIL;
}
ast_test_status_update(test, "Creating handle that should NEVER block on read\n");
if ((fd[1] = open("/dev/zero", O_RDONLY)) < 0) {
ast_test_status_update(test, "Unable to open a readable handle to /dev/zero: %s\n", strerror(errno));
close(fd[0]);
return AST_TEST_FAIL;
}
ast_test_status_update(test, "Creating handle that should block on read\n");
if (pipe(rdblocker) < 0) {
ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
close(fd[0]);
close(fd[1]);
return AST_TEST_FAIL;
}
#if FDNO > 3
ast_test_status_update(test, "Creating handle that should block on write\n");
if (pipe(wrblocker) < 0) {
ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
close(fd[0]);
close(fd[1]);
close(rdblocker[0]);
close(rdblocker[1]);
return AST_TEST_FAIL;
}
ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
ast_test_status_update(test, "Unable to start failsafe thread\n");
close(fd[0]);
close(fd[1]);
close(fd[2]);
close(rdblocker[0]);
close(rdblocker[1]);
close(wrblocker[0]);
close(wrblocker[1]);
return AST_TEST_FAIL;
}
/* Fill the pipe full of data */
ast_test_status_update(test, "Making pipe block on write\n");
for (i = 0; i < 4096; i++) { /* 1MB of data should be more than enough for any pipe */
errno = 0;
if (write(wrblocker[1], garbage, sizeof(garbage)) < sizeof(garbage)) {
ast_test_status_update(test, "Got %d\n", errno);
if (errno == EINTR && ++consec_interrupt > 1) {
break;
}
} else {
consec_interrupt = 0;
}
}
ast_test_status_update(test, "Cancelling failsafe thread.\n");
pthread_cancel(failsafe_tid);
pthread_kill(failsafe_tid, SIGURG);
pthread_join(failsafe_tid, NULL);
#endif
pfd[0].fd = fd[0];
pfd[1].fd = fd[1];
pfd[2].fd = rdblocker[0];
#if FDNO > 3
pfd[3].fd = wrblocker[1];
#endif
/* Need to ensure the infinite timeout doesn't stall the process */
ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
ast_test_status_update(test, "Unable to start failsafe thread\n");
close(fd[0]);
close(fd[1]);
close(rdblocker[0]);
close(rdblocker[1]);
#if FDNO > 3
close(wrblocker[0]);
close(wrblocker[1]);
#endif
return AST_TEST_FAIL;
}
RESET;
if ((res2 = ast_poll(pfd, FDNO, -1)) != 2) {
ast_test_status_update(test, "ast_poll does not return that only two handles are available (inf timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
RESET;
if ((res2 = ast_poll2(pfd, FDNO, NULL)) != 2) {
ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (inf timeout): %d %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
ast_test_status_update(test, "Cancelling failsafe thread.\n");
pthread_cancel(failsafe_tid);
pthread_kill(failsafe_tid, SIGURG);
pthread_join(failsafe_tid, NULL);
RESET;
if (ast_poll(pfd, FDNO, 0) != 2) {
ast_test_status_update(test, "ast_poll does not return that only two handles are available (0 timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
RESET;
if (ast_poll2(pfd, FDNO, &tv) != 2) {
ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (0 timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
RESET;
if (ast_poll(pfd, FDNO, 1) != 2) {
ast_test_status_update(test, "ast_poll does not return that only two handles are available (1ms timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
tv.tv_usec = 1000;
if (ast_poll2(pfd, FDNO, &tv) != 2) {
ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (1ms timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
close(fd[0]);
close(fd[1]);
close(rdblocker[0]);
close(rdblocker[1]);
#if FDNO > 3
close(wrblocker[0]);
close(wrblocker[1]);
#endif
return res;
}
#endif
static int unload_module(void)
{
#ifndef HAVE_SBIN_LAUNCHD
AST_TEST_UNREGISTER(poll_test);
#endif
return 0;
}
static int load_module(void)
{
#ifndef HAVE_SBIN_LAUNCHD
AST_TEST_REGISTER(poll_test);
#endif
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Poll test");
Loading…
Cancel
Save