Where the fd was added, compare the events with so->poll_events and call qemu_set_fd_handler() to update if it's changed. Where the fd was not added, call qemu_set_fd_handler() to remove it. Update slirp->do_slowtimo with a return value. For simplicity, G_IO_HUP and G_IO_ERR are unnecessary to be explicitly stated here, because they're implied in qemu_set_fd_handler.
For poll part, iohandler will call the read handler when there is an event, so the check in slirp_pollfds_poll() is removed. Signed-off-by: Fam Zheng <f...@redhat.com> --- slirp/slirp.c | 83 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/slirp/slirp.c b/slirp/slirp.c index 25cdca6..f648e6c 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -286,6 +286,44 @@ static void slirp_update_timeout(uint32_t *timeout) *timeout = t; } +static void slirp_icmp_read(void *opaque) +{ + struct socket *so = opaque; + icmp_receive(so); +} + +static bool slirp_poll_update_icmp(struct socket *so) +{ + bool ret = false; + bool old, new; + /* + * See if it's timed out + */ + if (so->so_expire) { + if (so->so_expire <= curtime) { + icmp_detach(so); + qemu_set_fd_handler(so->s, NULL, NULL, NULL); + return ret; + } else { + ret = true; /* Let socket expire */ + } + } + + old = so->poll_events == G_IO_IN; + new = !!(so->so_state & SS_ISFCONNECTED); + if (old != new) { + /* Need update */ + if (new) { + so->poll_events = G_IO_IN; + qemu_set_fd_handler(so->s, slirp_icmp_read, NULL, so); + } else { + so->poll_events = 0; + qemu_set_fd_handler(so->s, NULL, NULL, NULL); + } + } + return ret; +} + void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout) { Slirp *slirp; @@ -431,29 +469,7 @@ void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout) for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { so_next = so->so_next; - - so->pollfds_idx = -1; - - /* - * See if it's timed out - */ - if (so->so_expire) { - if (so->so_expire <= curtime) { - icmp_detach(so); - continue; - } else { - slirp->do_slowtimo = true; /* Let socket expire */ - } - } - - if (so->so_state & SS_ISFCONNECTED) { - GPollFD pfd = { - .fd = so->s, - .events = G_IO_IN | G_IO_HUP | G_IO_ERR, - }; - so->pollfds_idx = pollfds->len; - g_array_append_val(pollfds, pfd); - } + slirp->do_slowtimo |= slirp_poll_update_icmp(so); } } slirp_update_timeout(timeout); @@ -602,27 +618,6 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) sorecvfrom(so); } } - - /* - * Check incoming ICMP relies. - */ - for (so = slirp->icmp.so_next; so != &slirp->icmp; - so = so_next) { - int revents; - - so_next = so->so_next; - - revents = 0; - if (so->pollfds_idx != -1) { - revents = g_array_index(pollfds, GPollFD, - so->pollfds_idx).revents; - } - - if (so->s != -1 && - (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) { - icmp_receive(so); - } - } } if_start(slirp); -- 2.4.2