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