chiark / gitweb /
poll: Introduce and use BEFOREPOLL_WANT_FDS
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 20 Sep 2014 16:52:14 +0000 (17:52 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 2 Oct 2014 15:31:13 +0000 (16:31 +0100)
This helper macro provides a convenient implementation of the
beforepoll_fn interface for *nfds_io.  Use it everywhere.

This produces one bugfix: log_from_fd_beforepoll would fail to set
*nfds_io if it was finished,

This also arranges for many beforepoll callbacks to actually fail
properly with ERANGE if there is not enough space.  Previously they
would blithely write the next fd entry or two.  In practice the
provided fd array never runs out in the current code, so in these
cases we are just fixing latent bugs.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
log.c
process.c
secnet.h
site.c
slip.c
tun.c
udp.c

diff --git a/log.c b/log.c
index 326a891955fed55f07a21d9db86fda216a12f1c9..95f01b6898d0eec03bab58f18684fbf1c7d51c3f 100644 (file)
--- a/log.c
+++ b/log.c
@@ -485,9 +485,11 @@ static int log_from_fd_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
 {
     struct fdlog *st=sst;
     if (!st->finished) {
-       *nfds_io=1;
+       BEFOREPOLL_WANT_FDS(1);
        fds[0].fd=st->fd;
        fds[0].events=POLLIN;
+    } else {
+       BEFOREPOLL_WANT_FDS(0);
     }
     return 0;
 }
index 64683159ccc40be20132f5bc8d40beb89ed325c1..78d65364e75d61a8b98447a827b484c739f429a4 100644 (file)
--- a/process.c
+++ b/process.c
@@ -183,11 +183,7 @@ static beforepoll_fn signal_beforepoll;
 static int signal_beforepoll(void *st, struct pollfd *fds, int *nfds_io,
                             int *timeout_io)
 {
-    if (*nfds_io<1) {
-       *nfds_io=1;
-       return ERANGE;
-    }
-    *nfds_io=1;
+    BEFOREPOLL_WANT_FDS(1);
     fds[0].fd=spr;
     fds[0].events=POLLIN;
     return 0;
index 4e88345df921b96782898f6d3fe39f68091d89bc..f64382c35ff3fb038a94eab53c142b8358cde3aa 100644 (file)
--- a/secnet.h
+++ b/secnet.h
@@ -13,6 +13,7 @@
 #include <assert.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
 #include <sys/poll.h>
 #include <sys/types.h>
 #include <sys/time.h>
@@ -200,6 +201,16 @@ typedef int beforepoll_fn(void *st, struct pollfd *fds, int *nfds_io,
                          int *timeout_io);
 typedef void afterpoll_fn(void *st, struct pollfd *fds, int nfds);
 
+/* void BEFOREPOLL_WANT_FDS(int want);
+ *   Expects: int *nfds_io;
+ *   Can perform non-local exit.
+ * Checks whether there is space for want fds.  If so, sets *nfds_io.
+ * If not, sets *nfds_io and returns. */
+#define BEFOREPOLL_WANT_FDS(want) do{                          \
+    if (*nfds_io<(want)) { *nfds_io=(want); return ERANGE; }   \
+    *nfds_io=(want);                                           \
+  }while(0)
+
 /* Register interest in the main loop of the program. Before a call
    to poll() your supplied beforepoll function will be called. After
    the call to poll() the supplied afterpoll function will be called.
diff --git a/site.c b/site.c
index be0ae0cfcb017c3d3f640dd995173887d8d53126..d46e1002bdc8c9a8799c79783c92da1ea13450dd 100644 (file)
--- a/site.c
+++ b/site.c
@@ -1599,7 +1599,7 @@ static int site_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
 {
     struct site *st=sst;
 
-    *nfds_io=0; /* We don't use any file descriptors */
+    BEFOREPOLL_WANT_FDS(0); /* We don't use any file descriptors */
     st->now=*now;
 
     /* Work out when our next timeout is. The earlier of 'timeout' or
diff --git a/slip.c b/slip.c
index d8b32d8dbda79b5ad8ad4432be2adb4d3a166a10..1a60f40f64490f89f3b6533a55116b3d93d50b7e 100644 (file)
--- a/slip.c
+++ b/slip.c
@@ -170,13 +170,13 @@ static int userv_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
     struct userv *st=sst;
 
     if (st->rxfd!=-1) {
-       *nfds_io=2;
+       BEFOREPOLL_WANT_FDS(2);
        fds[0].fd=st->txfd;
        fds[0].events=0; /* Might want to pick up POLLOUT sometime */
        fds[1].fd=st->rxfd;
        fds[1].events=POLLIN;
     } else {
-       *nfds_io=0;
+       BEFOREPOLL_WANT_FDS(0);
     }
     return 0;
 }
diff --git a/tun.c b/tun.c
index 9ef3a9d627c161b96c50290b2985dcf7d307d176..102a24cabed62169b11a0f17cdc7f191fdb2e70f 100644 (file)
--- a/tun.c
+++ b/tun.c
@@ -98,7 +98,7 @@ static int tun_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
                          int *timeout_io)
 {
     struct tun *st=sst;
-    *nfds_io=1;
+    BEFOREPOLL_WANT_FDS(1);
     fds[0].fd=st->fd;
     fds[0].events=POLLIN;
     return 0;
diff --git a/udp.c b/udp.c
index 03025c7e438a3e2cd9f201617d63c28f91a14018..fcce186613b4de0424f2e94aab500a446b641f7b 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -75,11 +75,7 @@ static int udp_beforepoll(void *state, struct pollfd *fds, int *nfds_io,
 {
     int i;
     struct udp *st=state;
-    if (*nfds_io<st->n_socks) {
-       *nfds_io=st->n_socks;
-       return ERANGE;
-    }
-    *nfds_io=st->n_socks;
+    BEFOREPOLL_WANT_FDS(st->n_socks);
     for (i=0; i<st->n_socks; i++) {
        fds[i].fd=st->socks[i].fd;
        fds[i].events=POLLIN;