Boost logo

Boost-Commit :

From: chris_at_[hidden]
Date: 2007-10-06 20:11:26


Author: chris_kohlhoff
Date: 2007-10-06 20:11:25 EDT (Sat, 06 Oct 2007)
New Revision: 39752
URL: http://svn.boost.org/trac/boost/changeset/39752

Log:
The epoll_wait function can produce EPOLLHUP events for a descriptor even
if not specifically requested, resulting in a tight loop of calls to
epoll_wait. Delete a descriptor from epoll if an EPOLLHUP event is
received and there are no registered operations for the descriptor.

Text files modified:
   trunk/boost/asio/detail/epoll_reactor.hpp | 60 ++++++++++++++++++++++++++++-----------
   1 files changed, 43 insertions(+), 17 deletions(-)

Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp 2007-10-06 20:11:25 EDT (Sat, 06 Oct 2007)
@@ -156,6 +156,8 @@
       ev.data.fd = descriptor;
 
       int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
       if (result != 0)
       {
         boost::system::error_code ec(errno,
@@ -190,6 +192,8 @@
       ev.data.fd = descriptor;
 
       int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
       if (result != 0)
       {
         boost::system::error_code ec(errno,
@@ -220,6 +224,8 @@
       ev.data.fd = descriptor;
 
       int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
       if (result != 0)
       {
         boost::system::error_code ec(errno,
@@ -252,6 +258,8 @@
       ev.data.fd = descriptor;
 
       int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
       if (result != 0)
       {
         boost::system::error_code ec(errno,
@@ -420,23 +428,40 @@
         else
           more_writes = write_op_queue_.has_operation(descriptor);
 
- epoll_event ev = { 0, { 0 } };
- ev.events = EPOLLERR | EPOLLHUP;
- if (more_reads)
- ev.events |= EPOLLIN;
- if (more_writes)
- ev.events |= EPOLLOUT;
- if (more_except)
- ev.events |= EPOLLPRI;
- ev.data.fd = descriptor;
- int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
- if (result != 0)
+ if ((events[i].events == EPOLLHUP)
+ && !more_except && !more_reads && !more_writes)
         {
- ec = boost::system::error_code(errno,
- boost::asio::error::system_category);
- read_op_queue_.dispatch_all_operations(descriptor, ec);
- write_op_queue_.dispatch_all_operations(descriptor, ec);
- except_op_queue_.dispatch_all_operations(descriptor, ec);
+ // 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
+ // calls to epoll_wait.
+ epoll_event ev = { 0, { 0 } };
+ epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
+ }
+ else
+ {
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLERR | EPOLLHUP;
+ if (more_reads)
+ ev.events |= EPOLLIN;
+ if (more_writes)
+ ev.events |= EPOLLOUT;
+ if (more_except)
+ ev.events |= EPOLLPRI;
+ ev.data.fd = descriptor;
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ {
+ ec = boost::system::error_code(errno,
+ boost::asio::error::system_category);
+ read_op_queue_.dispatch_all_operations(descriptor, ec);
+ write_op_queue_.dispatch_all_operations(descriptor, ec);
+ except_op_queue_.dispatch_all_operations(descriptor, ec);
+ }
         }
       }
     }
@@ -532,7 +557,8 @@
 
     if (minimum_wait_duration > boost::posix_time::time_duration())
     {
- return minimum_wait_duration.total_milliseconds();
+ int milliseconds = minimum_wait_duration.total_milliseconds();
+ return milliseconds > 0 ? milliseconds : 1;
     }
     else
     {


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk