[Boost-bugs] [Boost C++ Libraries] #13468: asio receive buffer overwritten before handler called

Subject: [Boost-bugs] [Boost C++ Libraries] #13468: asio receive buffer overwritten before handler called
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2018-03-06 10:47:26


#13468: asio receive buffer overwritten before handler called
-------------------------------------------+----------------------------
 Reporter: Gary Bayliss <gary.bayliss@…> | Owner: chris_kohlhoff
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: asio
  Version: Boost 1.66.0 | Severity: Problem
 Keywords: |
-------------------------------------------+----------------------------
 I am developing on linux CentOS6.8

 Whilst using boost::asio::ip::udp::socket::async_receive_from, I have
 found that if packets arrive too quickly the receive buffer is overwritten
 before the handler is called, resulting in a loss of data.

 In order to resolve this in my implementation I have modified
 epoll_reactor::descriptor_state::perform_io to only process one entry from
 the EPOLLIN queue as below marked +++

 {{{
 operation* epoll_reactor::descriptor_state::perform_io(uint32_t events)
 {
   mutex_.lock();
   perform_io_cleanup_on_block_exit io_cleanup(reactor_);
   mutex::scoped_lock descriptor_lock(mutex_,
 mutex::scoped_lock::adopt_lock);

   // Exception operations must be processed first to ensure that any
   // out-of-band data is read before normal data.
   static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
   for (int j = max_ops - 1; j >= 0; --j)
   {
     if (events & (flag[j] | EPOLLERR | EPOLLHUP))
     {
       try_speculative_[j] = true;
       while (reactor_op* op = op_queue_[j].front())
       {
         if (reactor_op::status status = op->perform())
         {
           op_queue_[j].pop();
           io_cleanup.ops_.push(op);
           if (status == reactor_op::done_and_exhausted)
           {
             try_speculative_[j] = false;
             break;
           }
 +++ if ((events & EPOLLIN) && (flag[j] == EPOLLIN))
 +++ {
 +++ // only read one packet at a time
 +++ break;
 +++ }
         }
         else
           break;
       }
     }
   }

 }}}

   // The first operation will be returned for completion now. The others
 will
   // be posted for later by the io_cleanup object's destructor.
   io_cleanup.first_op_ = io_cleanup.ops_.front();
   io_cleanup.ops_.pop();
   return io_cleanup.first_op_;
 }

-- 
Ticket URL: <https://svn.boost.org/trac10/ticket/13468>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2018-03-06 10:53:01 UTC