diff options
author | Felix Fietkau <nbd@openwrt.org> | 2012-06-24 23:06:16 +0400 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2012-06-24 23:06:16 +0400 |
commit | 63bc6593c37b4757199fb65ec1fb607c5e5190e3 (patch) | |
tree | efa76cc3a16b5c1f895270cbcbdc84317c2fc7e0 /uloop.c | |
parent | eedf91d212caea67920848e1c7e9355173359986 (diff) |
uloop: prevent fd callbacks for unregistered fds by ensuring that pointers in the epoll array are cleared
Diffstat (limited to 'uloop.c')
-rw-r--r-- | uloop.c | 23 |
1 files changed, 20 insertions, 3 deletions
@@ -201,16 +201,26 @@ static int register_poll(struct uloop_fd *fd, unsigned int flags) return epoll_ctl(poll_fd, op, fd->fd, &ev); } +static int cur_fd, cur_nfds; +static struct epoll_event events[ULOOP_MAX_EVENTS]; + int uloop_fd_delete(struct uloop_fd *sock) { + int i; + + for (i = cur_fd + 1; i < cur_nfds; i++) { + if (events[i].data.ptr != sock) + continue; + + events[i].data.ptr = NULL; + } sock->registered = false; return epoll_ctl(poll_fd, EPOLL_CTL_DEL, sock->fd, 0); } static void uloop_run_events(int timeout) { - struct epoll_event events[ULOOP_MAX_EVENTS]; - int nfds, n; + int n, nfds; nfds = epoll_wait(poll_fd, events, ARRAY_SIZE(events), timeout); for(n = 0; n < nfds; ++n) @@ -218,6 +228,9 @@ static void uloop_run_events(int timeout) struct uloop_fd *u = events[n].data.ptr; unsigned int ev = 0; + if (!u) + continue; + if(events[n].events & EPOLLERR) { u->error = true; uloop_fd_delete(u); @@ -235,9 +248,13 @@ static void uloop_run_events(int timeout) if(events[n].events & EPOLLOUT) ev |= ULOOP_WRITE; - if(u->cb) + if(u->cb) { + cur_fd = n; + cur_nfds = nfds; u->cb(u, ev); + } } + cur_nfds = 0; } #endif |