[zeromq-dev] Epolling on FD doesn't work for 2.1.11
Robert G. Jakabosky
bobby at sharedrealm.com
Thu Mar 22 11:41:21 CET 2012
On Tuesday 20, Andrzej K. Haczewski wrote:
> First of all I'd like to say hello to everyone, since this is my first
> post here. So:
>
> Hello,
>
> I've been trying to integrate ZeroMQ with libev event loop and I've
> hit a strange behavior (or a bug?). In particular, as anyone
> integrating with event loop, I've been watching (libev calls it like
> that) my sockets for any input events, passing file descriptors taken
> using getsockopt(ZMQ_FD).
>
> How surprised I was that for REQ and REP sockets only REP socket
> received notifications. Trying to isolate an error I simulated the
> behavior using Python and epoll:
> http://pastebin.com/kiBtu4jv
>
> On my system (linux 3.1.6 amd64) and ZeroMQ 2.1.11 the output of that
> code looks like this:
> [(16, 1)]
> SUCCESSFULLY RECEIVED REQUEST!
> []
> []
> []
> []
> []
> []
> ...
>
> Upgrading ZeroMQ to 3.1.0 the situation changes dramatically,
> outputting what I expected:
> [(9, 1), (10, 1)]
> SUCCESSFULLY RECEIVED REQUEST!
> [(9, 1), (10, 1)]
> RECEIVED GOOD REPLY!
>
> Trying to get help on #zeromq I was told that it might be an issue
> with level-triggering epoll, so I tried switching to edge-triggered
> poll. Unfortunately it doesn't work for neither 2.1.11 nor 3.1.0.
zmq sockets are alway level-triggered. Your code should call
zmq_send/zmq_recv until it returns EAGAIN, then register the FD for read
events with your event loop. Your code also needs to alway pass the
ZMQ_NOBLOCK flag to zmq_send/zmq_recv.
For an lib-ev event loop use an idle watcher to call zmq_recv when it is not
block. Once zmq_recv returns EAGAIN, stop the idle watcher and start an io
watcher for read events. The ev_io callback needs to get the value of
ZMQ_EVENTS with zmq_getsockopt(), then check the events value for ZMQ_POLLIN.
As soon as ZMQ_EVENTS has ZMQ_POLLIN stop the io watcher and start the idle
watcher again.
Basically if the zmq socket is readable, your code must keep calling
zmq_recv() until it returns EAGAIN without waiting for another IO read event
from the event loop.
I have written an example [1] in Lua that reads from a zmq SUB socket using
the lib-ev event loop.
Also there is client [2] and server [3] example (using REQ/REP sockets) that
can use either lib-ev [4] or epoll [5] event loops.
I hope that helps.
1. https://github.com/Neopallium/lua-
zmq/blob/master/examples/subscriber_ev.lua
2. https://github.com/Neopallium/lua-zmq/blob/master/examples/client_poll.lua
3. https://github.com/Neopallium/lua-zmq/blob/master/examples/server_poll.lua
4. https://github.com/Neopallium/lua-zmq/blob/master/examples/poller/ev.lua
5. https://github.com/Neopallium/lua-zmq/blob/master/examples/poller/epoll.lua
--
Robert G. Jakabosky
More information about the zeromq-dev
mailing list