Would it be possible to write a unit test that reproduces the original
problem? It should be pretty easy to repro, right?

Neil

On Thu, May 12, 2016 at 1:50 AM,  <bmah...@apache.org> wrote:
> Repository: mesos
> Updated Branches:
>   refs/heads/master 95e670cd4 -> 28c085fca
>
>
> Fixed a head-of-line blocking bug in libevent SSL socket.
>
> Currently, the `accept_queue` is used to store connected sockets.
> However, we push socket futures into this queue *before* they
> complete the SSL handshake or are downgraded. This means that
> a future returned from the queue may remain pending. If the user
> writes a `Socket::accept` loop consuming accepted sockets they
> will experience head-of-line blocking while a slow handshake or
> downgrade is in progress.
>
> Review: https://reviews.apache.org/r/47192
>
>
> Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
> Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/28c085fc
> Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/28c085fc
> Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/28c085fc
>
> Branch: refs/heads/master
> Commit: 28c085fcad70de128d147b486264395318c4d1ec
> Parents: 95e670c
> Author: Benjamin Mahler <bmah...@apache.org>
> Authored: Tue May 10 15:33:13 2016 -0700
> Committer: Benjamin Mahler <bmah...@apache.org>
> Committed: Wed May 11 16:50:33 2016 -0700
>
> ----------------------------------------------------------------------
>  3rdparty/libprocess/src/libevent_ssl_socket.cpp | 17 ++++++++++++-----
>  3rdparty/libprocess/src/libevent_ssl_socket.hpp | 10 +++++-----
>  2 files changed, 17 insertions(+), 10 deletions(-)
> ----------------------------------------------------------------------
>
>
> http://git-wip-us.apache.org/repos/asf/mesos/blob/28c085fc/3rdparty/libprocess/src/libevent_ssl_socket.cpp
> ----------------------------------------------------------------------
> diff --git a/3rdparty/libprocess/src/libevent_ssl_socket.cpp 
> b/3rdparty/libprocess/src/libevent_ssl_socket.cpp
> index b829e7d..2f844c2 100644
> --- a/3rdparty/libprocess/src/libevent_ssl_socket.cpp
> +++ b/3rdparty/libprocess/src/libevent_ssl_socket.cpp
> @@ -843,8 +843,9 @@ Future<Socket> LibeventSSLSocketImpl::accept()
>    // We explicitly specify the return type to avoid a type deduction
>    // issue in some versions of clang. See MESOS-2943.
>    return accept_queue.get()
> -    .then([](const Future<Socket>& future) -> Future<Socket> {
> -      return future;
> +    .then([](const Future<Socket>& socket) -> Future<Socket> {
> +      CHECK(!socket.isPending());
> +      return socket;
>      });
>  }
>
> @@ -920,9 +921,15 @@ void 
> LibeventSSLSocketImpl::accept_callback(AcceptRequest* request)
>  {
>    CHECK(__in_event_loop__);
>
> -  // Enqueue a potential socket that we will set up SSL state for and
> -  // verify.
> -  accept_queue.put(request->promise.future());
> +  Queue<Future<Socket>> accept_queue_ = accept_queue;
> +
> +  // After the socket is accepted, it must complete the SSL
> +  // handshake (or be downgraded to a regular socket) before
> +  // we put it in the queue of connected sockets.
> +  request->promise.future()
> +    .onAny([accept_queue_](Future<Socket> socket) mutable {
> +      accept_queue_.put(socket);
> +    });
>
>    // If we support downgrading the connection, first wait for this
>    // socket to become readable. We will then MSG_PEEK it to test
>
> http://git-wip-us.apache.org/repos/asf/mesos/blob/28c085fc/3rdparty/libprocess/src/libevent_ssl_socket.hpp
> ----------------------------------------------------------------------
> diff --git a/3rdparty/libprocess/src/libevent_ssl_socket.hpp 
> b/3rdparty/libprocess/src/libevent_ssl_socket.hpp
> index e773fad..9b6ba64 100644
> --- a/3rdparty/libprocess/src/libevent_ssl_socket.hpp
> +++ b/3rdparty/libprocess/src/libevent_ssl_socket.hpp
> @@ -170,11 +170,11 @@ private:
>    // event loop until it is destroyed.
>    std::weak_ptr<LibeventSSLSocketImpl>* event_loop_handle;
>
> -  // This queue stores buffered accepted sockets. 'Queue' is a thread
> -  // safe queue implementation, and the event loop pushes connected
> -  // sockets onto it, the 'accept()' call pops them off. We wrap these
> -  // sockets with futures so that we can pass errors through and chain
> -  // futures as well.
> +  // This queue stores accepted sockets that are considered connected
> +  // (either the SSL handshake has completed or the socket has been
> +  // downgraded). The 'accept()' call returns sockets from this queue.
> +  // We wrap the socket in a 'Future' so that we can pass failures or
> +  // discards through.
>    Queue<Future<Socket>> accept_queue;
>
>    Option<std::string> peer_hostname;
>

Reply via email to