diff options
author | Stefan Metzmacher <metze@samba.org> | 2013-02-22 21:45:11 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2013-03-01 11:59:51 -0800 |
commit | 6952d761d2b9ebb2457916d9dfa3f070c0f62228 (patch) | |
tree | 8feb4f4ced2f582278c48faeb78f21adb6aea78b /lib/tevent | |
parent | de0204ccae514b26524893b51414c6c772a35a55 (diff) | |
download | samba-6952d761d2b9ebb2457916d9dfa3f070c0f62228.tar.gz samba-6952d761d2b9ebb2457916d9dfa3f070c0f62228.tar.bz2 samba-6952d761d2b9ebb2457916d9dfa3f070c0f62228.zip |
tevent: ignore POLLNVAL from poll() and disable the event
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/tevent')
-rw-r--r-- | lib/tevent/tevent_poll.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c index 763a139c7c..867d951ee1 100644 --- a/lib/tevent/tevent_poll.c +++ b/lib/tevent/tevent_poll.c @@ -501,6 +501,7 @@ static int poll_event_loop_poll(struct tevent_context *ev, int timeout = -1; int poll_errno; struct tevent_fd *fde = NULL; + unsigned i; if (ev->signal_events && tevent_common_check_signal(ev)) { return 0; @@ -555,6 +556,26 @@ static int poll_event_loop_poll(struct tevent_context *ev, pfd = &poll_ev->fds[idx]; + if (pfd->revents & POLLNVAL) { + /* + * the socket is dead! this should never + * happen as the socket should have first been + * made readable and that should have removed + * the event, so this must be a bug. + * + * We ignore it here to match the epoll + * behavior. + */ + tevent_debug(ev, TEVENT_DEBUG_ERROR, + "POLLNVAL on fde[%p] fd[%d] - disabling\n", + fde, pfd->fd); + poll_ev->fdes[idx] = NULL; + poll_ev->deleted = true; + DLIST_REMOVE(ev->fd_events, fde); + fde->event_ctx = NULL; + continue; + } + if (pfd->revents & (POLLHUP|POLLERR)) { /* If we only wait for TEVENT_FD_WRITE, we should not tell the event handler about it, @@ -575,7 +596,29 @@ static int poll_event_loop_poll(struct tevent_context *ev, } if (flags != 0) { fde->handler(ev, fde, flags, fde->private_data); - break; + return 0; + } + } + + for (i = 0; i < poll_ev->num_fds; i++) { + if (poll_ev->fds[i].revents & POLLNVAL) { + /* + * the socket is dead! this should never + * happen as the socket should have first been + * made readable and that should have removed + * the event, so this must be a bug or + * a race in the poll_mt usage. + */ + fde = poll_ev->fdes[i]; + tevent_debug(ev, TEVENT_DEBUG_WARNING, + "POLLNVAL on dangling fd[%d] fde[%p] - disabling\n", + poll_ev->fds[i].fd, fde); + poll_ev->fdes[i] = NULL; + poll_ev->deleted = true; + if (fde != NULL) { + DLIST_REMOVE(ev->fd_events, fde); + fde->event_ctx = NULL; + } } } |