<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">On 2/12/16 3:13 PM, Thomas Markwalder
      wrote:<br>
    </div>
    <blockquote cite="mid:56BE3CE3.7020203@isc.org" type="cite">
      <meta http-equiv="Context-Type" content="text/html; charset=utf-8">
      <div class="moz-cite-prefix">On 2/4/16 6:26 PM, Derek Lambert
        wrote:<br>
      </div>
      <blockquote
cite="mid:CAJc6QqTuiV+unDntzOYXMvYypVPspv_ugdhhtOiAnjDGBjjPSQ@mail.gmail.com"
        type="cite">
        <div dir="ltr">If it helps here's a strace of the server without
          optimizations, it just waits in the last call to epoll_wait. I
          gave it 5 minutes before killing it:
          <div><br>
          </div>
        </div>
      </blockquote>
      : removed for brevity...<br>
      <blockquote
cite="mid:CAJc6QqTuiV+unDntzOYXMvYypVPspv_ugdhhtOiAnjDGBjjPSQ@mail.gmail.com"
        type="cite">
        <div dir="ltr"><br>
        </div>
        <div class="gmail_extra">
          <div class="gmail_quote">
            <blockquote class="gmail_quote"><span class=""> </span><span
                class="">> Thanks for the tip! This will at least
                allow me to move forward with my<br>
                > testing.<br>
              </span>Thanks for sharing the results. Ok, so it seems
              this issue occurring<br>
              when Kea is built with gcc 5 and optimizations are
              enabled. Hopefully<br>
              that piece of information will be useful in debugging.<br>
              <span class="HOEnZb"><br>
                Tomek<br>
                <br>
              </span></blockquote>
          </div>
          <br>
        </div>
        <br>
        <fieldset class="mimeAttachmentHeader"></fieldset>
        <br>
        <pre wrap="">_______________________________________________
Kea-users mailing list
<a moz-do-not-send="true" class="moz-txt-link-abbreviated" href="mailto:Kea-users@lists.isc.org">Kea-users@lists.isc.org</a>
<a moz-do-not-send="true" class="moz-txt-link-freetext" href="https://lists.isc.org/mailman/listinfo/kea-users">https://lists.isc.org/mailman/listinfo/kea-users</a>
</pre>
      </blockquote>
      <tt>Hello all:<br>
        <br>
        After some rather painful debugging, we have isolated the issue
        to a boost::asio function from which the gcc optimizer is
        incorrectly removing some critical checks:<br>
        <br>
        <br>
        (from the source file:
        /usr/include/boost/asio/detail/impl/socket_ops.ipp)<br>
        <br>
         :<br>
        bool non_blocking_recvfrom(socket_type s,<br>
            buf* bufs, size_t count, int flags,<br>
            socket_addr_type* addr, std::size_t* addrlen,<br>
            boost::system::error_code& ec, size_t&
        bytes_transferred)<br>
        {<br>
          for (;;)<br>
          {<br>
            // Read some data.<br>
            signed_size_type bytes = socket_ops::recvfrom(<br>
                s, bufs, count, flags, addr, addrlen, ec);<br>
        <br>
            // Retry operation if interrupted by signal.<br>
            if (ec == boost::asio::error::interrupted)<br>
              continue;<br>
        <br>
            // Check if we need to run the operation again.<br>
            if (ec_local == boost::asio::error::would_block<br>
                || ec_local == boost::asio::error::try_again)<br>
              return false;<br>
        <br>
            // Operation is complete.<br>
            if (bytes >= 0)<br>
            {<br>
              ec = boost::system::error_code();<br>
              bytes_transferred = bytes;<br>
            }<br>
            else<br>
              bytes_transferred = 0;<br>
        <br>
            return true;<br>
          }<br>
        }<br>
           :<br>
        <br>
        The checks against the value of "ec" after the call to
        "recvfrom()" are optimized out causing the function to always
        return true, even if the read was interrupted (should continue)
        or the call would block (should return false).  In either case,
        the true return causes the callback registered to the socket to
        be invoked when it should not be.  The DHCP_DDNS library code
        interprets this as a failed read.<br>
        <br>
        This manifests itself in D2 as an infinite loop of failed
        reads.  I'll be opening up an issue the GCC folks as well as
        coming up with a short-term solution, which will likely turn off
        optimization for the asio code.<br>
        <br>
        There is Trac ticket associated with this already, <a
          moz-do-not-send="true" class="moz-txt-link-freetext"
          href="http://kea.isc.org/ticket/4243"><a class="moz-txt-link-freetext" href="http://kea.isc.org/ticket/4243">http://kea.isc.org/ticket/4243</a></a>.<br>
        <br>
        <br>
        Thomas Markwalder<br>
        ISC Software Engineering<br>
      </tt> <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
Kea-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:Kea-users@lists.isc.org">Kea-users@lists.isc.org</a>
<a class="moz-txt-link-freetext" href="https://lists.isc.org/mailman/listinfo/kea-users">https://lists.isc.org/mailman/listinfo/kea-users</a>
</pre>
    </blockquote>
    <tt>The code snippet above is slightly wrong (I've been mucking with
      it), here is the pristine code:<br>
      <br>
      bool non_blocking_recvfrom(socket_type s,<br>
          buf* bufs, size_t count, int flags,<br>
          socket_addr_type* addr, std::size_t* addrlen,<br>
          boost::system::error_code& ec, size_t&
      bytes_transferred)<br>
      {<br>
        for (;;)<br>
        {<br>
          // Read some data.<br>
          signed_size_type bytes = socket_ops::recvfrom(<br>
              s, bufs, count, flags, addr, addrlen, ec);<br>
      <br>
          // Retry operation if interrupted by signal.<br>
          if (ec == boost::asio::error::interrupted)<br>
            continue;<br>
      <br>
          // Check if we need to run the operation again.<br>
          if (ec == boost::asio::error::would_block<br>
              || ec == boost::asio::error::try_again)<br>
            return false;<br>
      <br>
          // Operation is complete.<br>
          if (bytes >= 0)<br>
          {<br>
            ec = boost::system::error_code();<br>
            bytes_transferred = bytes;<br>
          }<br>
          else<br>
            bytes_transferred = 0;<br>
      <br>
          return true;<br>
        }<br>
      }<br>
      <br>
    </tt>
  </body>
</html>