]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: poll: do not use FD_* macros anymore
authorWilly Tarreau <w@1wt.eu>
Sun, 31 Mar 2013 12:06:57 +0000 (14:06 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 31 Mar 2013 13:01:01 +0000 (15:01 +0200)
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.

src/ev_poll.c

index e3ea4db63cb09e4e5112f5f3239714a4a1e19e66..537157fcabb4b253a838fa0c98dff6cc7efe626b 100644 (file)
 #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]);
 }
 
 /*
@@ -62,14 +77,14 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
                        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 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
        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
-
-#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++;
-                               }
+               if (!(rn|wn))
+                       continue;
+
+               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 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
 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;