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, 6 Oct 2014 16:53:13 +0000 (17:53 +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 629851b2ac183234cf00ba8ca773c1e730183b2d..0e2e1f7819057a17b8911a7c1647cb0cd70508de 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 d0755da2fdc3cc308e412ad7d060430c0b7bec97..abbaa1e594e655b8124e09feefd38fb9884c027e 100644 (file)
--- a/site.c
+++ b/site.c
@@ -1600,7 +1600,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 8ae5671bd64a38a16914997ffe035f65e0b4d26f..98da30d6f66f391ac8944a4e2a835dacf257572e 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -87,11 +87,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;