diff options
author | rofl0r <rofl0r@users.noreply.github.com> | 2020-09-15 19:29:03 +0100 |
---|---|---|
committer | rofl0r <rofl0r@users.noreply.github.com> | 2020-09-15 23:12:00 +0100 |
commit | 10cdee3bc55274d7f6278cdd0c66edacb5b520a5 (patch) | |
tree | 6600c23e0735cc5fdb8af0512572ad6631bc584d /src/mypoll.c | |
parent | 0c8275a90ed16c4230fb311aebbf34c5667667c7 (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.c | 42 |
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; +} + |