summaryrefslogtreecommitdiffhomepage
path: root/src/mypoll.c
diff options
context:
space:
mode:
authorrofl0r <rofl0r@users.noreply.github.com>2020-09-15 19:29:03 +0100
committerrofl0r <rofl0r@users.noreply.github.com>2020-09-15 23:12:00 +0100
commit10cdee3bc55274d7f6278cdd0c66edacb5b520a5 (patch)
tree6600c23e0735cc5fdb8af0512572ad6631bc584d /src/mypoll.c
parent0c8275a90ed16c4230fb311aebbf34c5667667c7 (diff)
prepare transition to poll()
usage of select() is inefficient (because a huge fd_set array has to be initialized on each call) and insecure (because an fd >= FD_SETSIZE will cause out-of-bounds accesses using the FD_*SET macros, and a system can be set up to allow more than that number of fds using ulimit). for the moment we prepared a poll-like wrapper that still runs select() to test for regressions, and so we have fallback code for systems without poll().
Diffstat (limited to 'src/mypoll.c')
-rw-r--r--src/mypoll.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/mypoll.c b/src/mypoll.c
new file mode 100644
index 0000000..0e06805
--- /dev/null
+++ b/src/mypoll.c
@@ -0,0 +1,42 @@
+#include "mypoll.h"
+
+#define MYPOLL_READ (1<<1)
+#define MYPOLL_WRITE (1<<2)
+
+int mypoll(pollfd_struct* fds, int nfds, int timeout) {
+ fd_set rset, wset, *r=0, *w=0;
+ int i, ret, maxfd=-1;
+ struct timeval tv = {0}, *t = 0;
+
+ for(i=0; i<nfds; ++i) {
+ if(fds[i].events & MYPOLL_READ) r = &rset;
+ if(fds[i].events & MYPOLL_WRITE) w = &wset;
+ if(r && w) break;
+ }
+ if(r) FD_ZERO(r);
+ if(w) FD_ZERO(w);
+ for(i=0; i<nfds; ++i) {
+ if(fds[i].fd > maxfd) maxfd = fds[i].fd;
+ if(fds[i].events & MYPOLL_READ) FD_SET(fds[i].fd, r);
+ if(fds[i].events & MYPOLL_WRITE) FD_SET(fds[i].fd, w);
+ }
+
+ if(timeout >= 0) t = &tv;
+ if(timeout > 0) tv.tv_sec = timeout;
+
+ ret = select(maxfd+1, r, w, 0, t);
+
+ switch(ret) {
+ case -1:
+ case 0:
+ return ret;
+ }
+
+ for(i=0; i<nfds; ++i) {
+ fds[i].revents = 0;
+ if(r && FD_ISSET(fds[i].fd, r)) fds[i].revents |= MYPOLL_READ;
+ if(w && FD_ISSET(fds[i].fd, w)) fds[i].revents |= MYPOLL_WRITE;
+ }
+ return ret;
+}
+