[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] event_add fails with ENOENT when on epoll



Thanks to everyone replied!

The problem is that it's not always possible for me to delete the
event before the socket is closed.

In gevent, events are setup and deleted by the library, on behalf of the user.
Suppose a user has created and connected a new gevent.socket.socket
instance and called

  data = sock.recv(1024)

on it. What will happen here under the hood is this:
 - new READ event is created and added to the event loop
 - the current coroutine is paused until event's callback is called by
libevent which in turn un-pauses the coroutine.

So it makes regular sequential code use event loop. It can even
replace threading with compatible
coroutine-based functions and threading program becomes epoll-powered
under the hood. Coroutines
take much less memory than threads so it's about as scalable as if it
was written using pyevent or twisted.

Despite looking crazy, it works quite well.

However, some libraries might close the socket while using it in
another thread. I wouldn't mind if everything
related to this socket failed, but the problem is that a seemingly
unrelated socket can fail because
it happened to re-use a file descriptor.

One approach to fix it would be for gevent.socket.socket to maintain a
list of all events it used and delete those events. However, this
seems like a duplication - libevent already knows which events are
related to this fd.

Hope that explains the problem.

Another way to observe this issue is to close a socket that I passed
to evhttp - in this case I don't even have
an access to the underlying event. I know I shouldn't close a socket
like that, but it would it be nice if failure was contained inside
evhttp and not affected other parts of the application.

I'm not sure if it's possible to make libevent "just work" here?

For example, would it be wrong to intercept ENOENT in event_add() then
delete the existing events and retry?

On Wed, Apr 21, 2010 at 12:20 AM, Nick Mathewson <nickm@xxxxxxxxxxxxx> wrote:
> On Mon, Apr 19, 2010 at 11:24 PM, Denis Bilenko <denis.bilenko@xxxxxxxxx> wrote:
>> Hi,
>>
>> I've run into an issue where event_add() fails with ENOENT.
>> This happens when a socket reuses a descriptor that was recently
>> closed and was used before with another event.
>>
>> The details are below. The question I have is - what are the ways to
>> work around this?
>>
>
> You must never modify an event that is currently pending.  If you want
> to reassign it, you need to call event_del(), then modify it, then
> call event_add().
>
> For some backends (like epoll and kqueue) you need to call event_del()
> on the event when you close the socket, and then event_add() again,
> even if the fd didn't change: as far as the kernel is concerned, it is
> no longer interested in tracking fd, once the socket has closed.
>
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.