[zeromq-dev] ZeroMQ integration with GLib main event loop

Alexander Yanin sashayanin at gmail.com
Thu Jul 27 16:03:05 CEST 2017


Hi,

Thank you for the provided article. This article covers the main approach
to integrating zmq fd into event loops more precisely than stackoverflow
threads I've linked to my question. But it seems that there is still no
answer to my question there, because my problem is in the very beginning of
an integration process - I never get my IO_IN callback triggered :)
In other words, when I call `recv` method in a for loop directly, I got
data, but when I connect zmq file descriptor to glib event loop to listen
to IO_IN conditions, lambda function that handles such events is never
called.
I've also tried connecting to other conditions than IO_IN, actually to all
others (IO_ERR, IO_PRI, etc), but the result was the same except with
IO_OUT. IO_OUT condition triggers the callback, but writing to fd is not my
case, as I am using ZMQ_SUB socket which is only for read purpose.

2017-07-27 15:55 GMT+03:00 Luca Boccassi <luca.boccassi at gmail.com>:

> On Thu, 2017-07-27 at 15:02 +0300, Alexander Yanin wrote:
> > I am trying to integrate ZeroMQ into my Glib main event loop. As I
> > have
> > seen on the official ZeroMQ FAQ and API reference and on some
> > stackoverflow
> > threads (zeromq glib main loop integration
> > <https://stackoverflow.com/questions/6695863/zeromq-glib-main-loop-in
> > tegration>
> > and How to use ZeroMQ in an GTK/QT/Clutter application?
> > <https://stackoverflow.com/questions/6452131/how-to-use-zeromq-in-an-
> > gtk-qt-clutter-application>),
> > to do this I need to get ZeroMQ FD and then connect it to existing
> > event
> > loop. But, unfortunately, In my case this does not work.
> >
> > here is the code:
> >
> > RefPtr<IOChannel> zmq_in;
> > zmq::context_t context (1);
> > zmq::socket_t subscriber (context, ZMQ_SUB);
> >
> > subscriber.connect("tcp://localhost:5556");const char *filter =
> > "10001 ";
> > subscriber.setsockopt(ZMQ_SUBSCRIBE, filter, strlen (filter));
> > const auto read_zmq = [this, &subscriber](Glib::IOCondition c) ->
> > bool {
> >     std::cout << " Received message on zmq!" << std::endl;
> >     int zipcode, temperature, relhumidity;
> >     zmq::message_t update;
> >     subscriber.recv(&update);
> >     std::istringstream iss(static_cast<char*>(update.data()));
> >     iss >> zipcode >> temperature >> relhumidity;
> >     std::cout << "Zipcode: " << zipcode << " Temperature: " <<
> > temperature
> >               << "Humidity: " << relhumidity;
> >     return true;};
> > for (int i = 0; i < 10 ; i++) {
> >     int zipcode, temperature, relhumidity;
> >     zmq::message_t update;
> >     subscriber.recv(&update);
> >     std::istringstream iss(static_cast<char*>(update.data()));
> >     iss >> zipcode >> temperature >> relhumidity;
> >     std::cout << "Zipcode: " << zipcode << "  Temperature: " <<
> > temperature
> >               << "  Humidity: " << relhumidity << std::endl;}
> > int fd = subscriber.getsockopt<int>(ZMQ_FD);
> > zmq_in = IOChannel::create_from_fd(fd);
> > Glib::signal_io().connect(read_zmq, zmq_in, Glib::IO_IN);
> >
> > What really happens when the code is executed: 10 messages are
> > successfully
> > received from Publisher (another process) in the for loop, but when
> > it
> > comes to receiving messages from the Glib main event loop, my c++
> > lambda is
> > never called :(
> >
> > Here is the Publisher code in C almost completely taken from ZeroMQ
> > Guide:
> >
> > #include <zmq.h>#include <stdio.h>#include <unistd.h>#include
> > <string.h>#include <assert.h>#include <stdlib.h>
> > int main (void){
> >         //  Prepare our context and publisher
> >         void *context = zmq_ctx_new ();
> >         void *publisher = zmq_socket (context, ZMQ_PUB);
> >         int rc = zmq_bind (publisher, "tcp://*:5556");
> >         assert (rc == 0);
> >
> >         //  Initialize random number generator
> >         while (1) {
> >                 //  Get values that will fool the boss
> >                 int zipcode, temperature, relhumidity;
> >                 zipcode     = rand () % 100000;
> >                 temperature = (rand () % 215) - 80;
> >                 relhumidity = (rand () % 50) + 10;
> >
> >                 //  Send message to all subscribers
> >                 char update [20];
> >                 sprintf (update, "%05d %d %d", zipcode, temperature,
> > relhumidity);
> >                 zmq_send (publisher, update, 20, 0);
> >                 int ev;
> >                 size_t sizeof_ev = sizeof(ev);
> >         }
> >         zmq_close (publisher);
> >         zmq_ctx_destroy (context);
> >         return 0;}
> >
> > So where is the problem?
> >
> > P.S.:I am using glibmm c++ binding to Glib. My OS is Fedora 26. My
> > ZeroMQ
> > version is 4.1.6
>
> Hi,
>
> I have no idea about that specific c++ glib binding, but as the answer
> on the first link you posted says you can't just poll a ZMQ socket, you
> need to get the file descriptor via the ZMQ_FD socket option and feed
> that to the poll, and then read in a loop as long as the ZMQ_EVENTS
> socket options returns ZMQ_POLLIN.
>
> This is because those FDs are edge triggered:
>
> https://funcptr.net/2012/09/10/zeromq---edge-triggered-notification/
>
> --
> Kind regards,
> Luca Boccassi
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> https://lists.zeromq.org/mailman/listinfo/zeromq-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20170727/a3974e7b/attachment.htm>


More information about the zeromq-dev mailing list