From 71d47ca98c463e775fb50acc6a962d4d90a90fc9 Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Fri, 8 Aug 2008 14:47:58 +0000 Subject: [PATCH] Fix a tight spin on epoll (or /dev/poll) that occurs when the EPOLLERR and EPOLLHUP events are reported for a descriptor and there are no pending operations. [SVN r48031] --- include/boost/asio/detail/dev_poll_reactor.hpp | 15 ++++++++------- include/boost/asio/detail/epoll_reactor.hpp | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/boost/asio/detail/dev_poll_reactor.hpp b/include/boost/asio/detail/dev_poll_reactor.hpp index aa863d8b..2d233194 100644 --- a/include/boost/asio/detail/dev_poll_reactor.hpp +++ b/include/boost/asio/detail/dev_poll_reactor.hpp @@ -423,14 +423,15 @@ private: else more_writes = write_op_queue_.has_operation(descriptor); - if ((events[i].events == POLLHUP) - && !more_except && !more_reads && !more_writes) + if ((events[i].events & (POLLERR | POLLHUP)) != 0 + && (events[i].events & ~(POLLERR | POLLHUP)) == 0 + && !more_except && !more_reads && !more_writes) { - // If we have only an POLLHUP event and no operations associated - // with the descriptor then we need to delete the descriptor from - // /dev/poll. The poll operation might produce POLLHUP events even - // if they are not specifically requested, so if we do not remove the - // descriptor we can end up in a tight polling loop. + // If we have an event and no operations associated with the + // descriptor then we need to delete the descriptor from /dev/poll. + // The poll operation can produce POLLHUP or POLLERR events when there + // is no operation pending, so if we do not remove the descriptor we + // can end up in a tight polling loop. ::pollfd ev = { 0 }; ev.fd = descriptor; ev.events = POLLREMOVE; diff --git a/include/boost/asio/detail/epoll_reactor.hpp b/include/boost/asio/detail/epoll_reactor.hpp index 04609aff..c54423bb 100644 --- a/include/boost/asio/detail/epoll_reactor.hpp +++ b/include/boost/asio/detail/epoll_reactor.hpp @@ -497,14 +497,15 @@ private: else more_writes = write_op_queue_.has_operation(descriptor); - if ((events[i].events == EPOLLHUP) - && !more_except && !more_reads && !more_writes) + if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0 + && (events[i].events & ~(EPOLLERR | EPOLLHUP)) == 0 + && !more_except && !more_reads && !more_writes) { - // If we have only an EPOLLHUP event and no operations associated - // with the descriptor then we need to delete the descriptor from - // epoll. The epoll_wait system call will produce EPOLLHUP events - // even if they are not specifically requested, so if we do not - // remove the descriptor we can end up in a tight loop of repeated + // If we have an event and no operations associated with the + // descriptor then we need to delete the descriptor from epoll. The + // epoll_wait system call can produce EPOLLHUP or EPOLLERR events + // when there is no operation pending, so if we do not remove the + // descriptor we can end up in a tight loop of repeated // calls to epoll_wait. epoll_event ev = { 0, { 0 } }; epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);