diff options
author | Stefan Metzmacher <metze@samba.org> | 2013-02-22 21:45:11 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2013-03-06 10:12:00 +0100 |
commit | d90aebf294de897588a9275bdb538accf2958f58 (patch) | |
tree | 75319678045cb8d5245b59beb9fe7dcfce0a31db /lib | |
parent | aae4312b745cd2e40ca7a224831745e7a6e9bba1 (diff) | |
download | samba-d90aebf294de897588a9275bdb538accf2958f58.tar.gz |
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')
-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 763a139c7c5..867d951ee1b 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; + } } } |