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>
Mon, 29 Sep 2014 15:01:05 +0000 (16:01 +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 cd2ea51e9212b96d1886d8ee158b052faf183a3b..d9bd400f95f200105f630498470018ce38bd3cbb 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 a35bb049ab9ff724ed6c2aa8c8f273cab9331695..a85333d9cee6ba63633148d1d9a9de2e68526db6 100644 (file)
--- a/site.c
+++ b/site.c
@@ -1598,7 +1598,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;