On Tue, Nov 11, 2008 at 7:17 PM, Erik Frey <er...@last.fm> wrote:

> I read in a previous thread that it's possible to use evhttp across
> multiple
> threads by creating an event_base per thread, and an evhttp instance per
> thread by calling evhttp_new.
>
> Am I correct in assuming that you create one socket fd and initialize it,
> then
> pass it to each thread's evhttp via evhttp_accept_socket?  I tried this,
> then
> put each thread into an event loop by calling event_base_loop, but had the
> following problem:
>
> After a few successful connections, libevent starts handing out warnings
> about
> failed accepts.  It seems that when a client tries to connect, the event is
> being handled by multiple threads - one is succesfully grabbing the
> accept()
> and others are bailing out.
>
> I'm most familiar with a single thread handling all the accepts() then
> handing
> the new fd to a worker thread - but evhttp seems structured to have
> multiple
> threads calling accept on the same fd.  Is this my problem, or a red
> herring?
>

Did you ever find a solution on this?

Disclaimer: I don't know much about the internals of libevent, or
threading/networking.

My uneducated guess is that each thread has registered a read event on the
listening socket. When a connection is made, the read event is triggered in
every thread, and they all try to accept and only one gets it in the end.
See: http://en.wikipedia.org/wiki/Thundering_herd_problem

If this is the problem, then one possible solution on linux would be to
followup this discussion (
http://linux.derkeiler.com/Mailing-Lists/Kernel/2007-05/msg02452.html) about
an epoll patch to solve this problem:

If multiple threads are parked on epoll_wait (on a single epoll fd) and
events become available, epoll performs a wake up of all threads of the
poll wait list, causing a thundering herd of processes trying to grab
the eventpoll lock.

This patch addresses this by using exclusive waiters (wake one). Once
the exclusive thread finishes transferring it's events, a new thread
is woken if there are more events available.


I think the proper alternative is to hook into evhttp after the connection
has already been accepted. You would have a single thread (acceptor) which
accepts connections, and then passes the fd off to a worker thread. The
worker thread would receive an fd from the acceptor thread, and then call
evhttp_get_request with the fd as one of the arguments. As far as I can
tell, this will create an evcon and add it to the evhttp, and start reading
the request, as you'd expect. You may have to do something special to
initialize/start evhttp without it actually listening for connections.

As for the mechanism you actually pass the fds back and forth, i'm not
really sure. Pipes maybe? In-memory queues? You indicated that you're
already familiar with this type of programming with libevent; could you let
me know how this actually works?

If, on the other hand, you have a more reasonable solution, please do let me
know! I may be facing this problem soon myself.

-Michael Carter
_______________________________________________
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users

Reply via email to