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 <ni...@freehaven.net> wrote: > On Mon, Apr 19, 2010 at 11:24 PM, Denis Bilenko <denis.bile...@gmail.com> > 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 majord...@freehaven.net with unsubscribe libevent-users in the body.