Re: [Boost-bugs] [Boost C++ Libraries] #5021: io_service destructor hangs on Mac OS X

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #5021: io_service destructor hangs on Mac OS X
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2011-02-23 23:26:36


#5021: io_service destructor hangs on Mac OS X
------------------------------------------------+---------------------------
  Reporter: Remko Tronçon <remko@…> | Owner: chris_kohlhoff
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: asio
   Version: Boost 1.45.0 | Severity: Problem
Resolution: | Keywords:
------------------------------------------------+---------------------------

Comment (by chris_kohlhoff):

 Thank you for the test case. I was able to reproduce the issue on several
 different Mac OS X 10.6 systems. It seems to be an OS bug triggered by the
 use of EV_ONESHOT. Please try the following diff to see if it fixes the
 problem for you, and doesn't cause any other problems. (Note that you may
 need to apply the diff by hand since it is made against the trunk.)

 {{{
 Index: boost/asio/detail/impl/kqueue_reactor.ipp
 ===================================================================
 --- boost/asio/detail/impl/kqueue_reactor.ipp (revision 69227)
 +++ boost/asio/detail/impl/kqueue_reactor.ipp (working copy)
 @@ -47,9 +47,9 @@
      interrupter_(),
      shutdown_(false)
  {
 - // The interrupter is put into a permanently readable state. Whenever
 we
 - // want to interrupt the blocked kevent call we register a one-shot
 read
 - // operation against the descriptor.
 + // The interrupter is put into a permanently readable state. Whenever
 we want
 + // to interrupt the blocked kevent call we register a read operation
 against
 + // the descriptor.
    interrupter_.interrupt();
  }

 @@ -108,15 +108,15 @@
    {
    case read_op:
      BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
 - EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
      break;
    case write_op:
      BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
 - EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
      break;
    case except_op:
      BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
 - EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, EV_OOBAND, 0, descriptor_data);
      break;
    }
    ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
 @@ -170,17 +170,17 @@
      {
      case read_op:
        BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
 - EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
        break;
      case write_op:
        BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
 - EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
        break;
      case except_op:
        if (!descriptor_data->op_queue_[read_op].empty())
          return; // Already registered for read events.
        BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
 - EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, EV_OOBAND, 0, descriptor_data);
        break;
      }

 @@ -290,7 +290,7 @@
      if (ptr == &interrupter_)
      {
        // No need to reset the interrupter since we're leaving the
 descriptor
 - // in a ready-to-read state and relying on one-shot notifications.
 + // in a ready-to-read state and relying on edge-triggered
 notifications.
      }
      else
      {
 @@ -339,17 +339,17 @@
        case EVFILT_READ:
          if (!descriptor_data->op_queue_[read_op].empty())
            BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
 - EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
          else if (!descriptor_data->op_queue_[except_op].empty())
            BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
 - EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, EV_OOBAND, 0, descriptor_data);
          else
            continue;
          break;
        case EVFILT_WRITE:
          if (!descriptor_data->op_queue_[write_op].empty())
            BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
 - EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
 + EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
          else
            continue;
          break;
 @@ -381,7 +381,7 @@
  {
    struct kevent event;
    BOOST_ASIO_KQUEUE_EV_SET(&event, interrupter_.read_descriptor(),
 - EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
 + EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &interrupter_);
    ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
  }
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/5021#comment:20>
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 : 2017-02-16 18:50:05 UTC