MEDIUM: poll: do not use FD_* macros anymore
Some recent glibc updates have added controls on FD_SET/FD_CLR/FD_ISSET
that crash the program if it tries to use a file descriptor larger than
FD_SETSIZE.
Do not rely on FD_* macros anymore and replace them with bit fields.
diff --git a/src/ev_poll.c b/src/ev_poll.c
index e3ea4db..537157f 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -27,18 +27,33 @@
#include <proto/task.h>
-static fd_set *fd_evts[2];
+static unsigned int *fd_evts[2];
/* private data */
static struct pollfd *poll_events = NULL;
-REGPRM1 static void __fd_clo(const int fd)
+static inline unsigned int hap_fd_isset(int fd, unsigned int *evts)
{
- FD_CLR(fd, fd_evts[DIR_RD]);
- FD_CLR(fd, fd_evts[DIR_WR]);
+ return evts[fd / (8*sizeof(*evts))] & (1U << (fd & (8*sizeof(*evts) - 1)));
}
+static inline void hap_fd_set(int fd, unsigned int *evts)
+{
+ evts[fd / (8*sizeof(*evts))] |= 1U << (fd & (8*sizeof(*evts) - 1));
+}
+
+static inline void hap_fd_clr(int fd, unsigned int *evts)
+{
+ evts[fd / (8*sizeof(*evts))] &= ~(1U << (fd & (8*sizeof(*evts) - 1)));
+}
+
+REGPRM1 static void __fd_clo(int fd)
+{
+ hap_fd_clr(fd, fd_evts[DIR_RD]);
+ hap_fd_clr(fd, fd_evts[DIR_WR]);
+}
+
/*
* Poll() poller
*/
@@ -62,14 +77,14 @@
if ((eo ^ en) & FD_EV_POLLED_RW) {
/* poll status changed, update the lists */
if ((eo & ~en) & FD_EV_POLLED_R)
- FD_CLR(fd, fd_evts[DIR_RD]);
+ hap_fd_clr(fd, fd_evts[DIR_RD]);
else if ((en & ~eo) & FD_EV_POLLED_R)
- FD_SET(fd, fd_evts[DIR_RD]);
+ hap_fd_set(fd, fd_evts[DIR_RD]);
if ((eo & ~en) & FD_EV_POLLED_W)
- FD_CLR(fd, fd_evts[DIR_WR]);
+ hap_fd_clr(fd, fd_evts[DIR_WR]);
else if ((en & ~eo) & FD_EV_POLLED_W)
- FD_SET(fd, fd_evts[DIR_WR]);
+ hap_fd_set(fd, fd_evts[DIR_WR]);
}
fdtab[fd].spec_e = (en << 4) + en; /* save new events */
@@ -92,33 +107,20 @@
fd_nbupdt = 0;
nbfd = 0;
- for (fds = 0; (fds * BITS_PER_INT) < maxfd; fds++) {
-
- rn = ((int*)fd_evts[DIR_RD])[fds];
- wn = ((int*)fd_evts[DIR_WR])[fds];
+ for (fds = 0; (fds * 8*sizeof(**fd_evts)) < maxfd; fds++) {
+ rn = fd_evts[DIR_RD][fds];
+ wn = fd_evts[DIR_WR][fds];
- if ((rn|wn)) {
- for (count = 0, fd = fds * BITS_PER_INT; count < BITS_PER_INT && fd < maxfd; count++, fd++) {
-#define FDSETS_ARE_INT_ALIGNED
-#ifdef FDSETS_ARE_INT_ALIGNED
+ if (!(rn|wn))
+ continue;
-#define WE_REALLY_KNOW_THAT_FDSETS_ARE_INTS
-#ifdef WE_REALLY_KNOW_THAT_FDSETS_ARE_INTS
- sr = (rn >> count) & 1;
- sw = (wn >> count) & 1;
-#else
- sr = FD_ISSET(fd&(BITS_PER_INT-1), (typeof(fd_set*))&rn);
- sw = FD_ISSET(fd&(BITS_PER_INT-1), (typeof(fd_set*))&wn);
-#endif
-#else
- sr = FD_ISSET(fd, fd_evts[DIR_RD]);
- sw = FD_ISSET(fd, fd_evts[DIR_WR]);
-#endif
- if ((sr|sw)) {
- poll_events[nbfd].fd = fd;
- poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0);
- nbfd++;
- }
+ for (count = 0, fd = fds * 8*sizeof(**fd_evts); count < 8*sizeof(**fd_evts) && fd < maxfd; count++, fd++) {
+ sr = (rn >> count) & 1;
+ sw = (wn >> count) & 1;
+ if ((sr|sw)) {
+ poll_events[nbfd].fd = fd;
+ poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0);
+ nbfd++;
}
}
}
@@ -202,21 +204,20 @@
REGPRM1 static int _do_init(struct poller *p)
{
__label__ fail_swevt, fail_srevt, fail_pe;
- int fd_set_bytes;
+ int fd_evts_bytes;
p->private = NULL;
- fd_set_bytes = sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE;
+ fd_evts_bytes = (global.maxsock + sizeof(**fd_evts) - 1) / sizeof(**fd_evts) * sizeof(**fd_evts);
- poll_events = (struct pollfd*)
- calloc(1, sizeof(struct pollfd) * global.maxsock);
+ poll_events = calloc(1, sizeof(struct pollfd) * global.maxsock);
if (poll_events == NULL)
goto fail_pe;
- if ((fd_evts[DIR_RD] = (fd_set *)calloc(1, fd_set_bytes)) == NULL)
+ if ((fd_evts[DIR_RD] = calloc(1, fd_evts_bytes)) == NULL)
goto fail_srevt;
- if ((fd_evts[DIR_WR] = (fd_set *)calloc(1, fd_set_bytes)) == NULL)
+ if ((fd_evts[DIR_WR] = calloc(1, fd_evts_bytes)) == NULL)
goto fail_swevt;
return 1;