1

I wrote a zmq proxy with zmq_poll() with 3 frontends and 3 backends and timeout of -1 which makes it endless. Frontend sockets use the connection-oriented tcp://-transport-class and are zmq_bind() associated with the tcp-ports on the host IP-address like tcp://192.168.1.1:1000.

Is there any way to break endless zmq_poll( ..., ..., -1 ) loop when my host's IP address changed?

while(1) {
    zmq_msg_t message;
    zmq_pollitem_t items [] = {
            { frontend1, 0, ZMQ_POLLIN, 0 },
            { backend1,  0, ZMQ_POLLIN, 0 },
    };
    zmq_poll (items, 2, -1);
    if(items[0].revents & ZMQ_POLLIN) {
     ...
    }
    if(items[1].revents & ZMQ_POLLIN) {
     ...
    }
}

I've tried to poll for events like ZMQ_POLLIN | ZMQ_POLLERR but when I changed host's IP address manually it does not return from a call to zmq_poll( ..., ..., -1 ).

user3666197
  • 1
  • 6
  • 50
  • 92
H00man
  • 375
  • 1
  • 7
  • 21
  • 1
    Something needs to send a signal to your program, when IP address changes. Signal then causes zmq_poll to return with EINTR error. Signal handler probably should raise some flag and in your main loop, you should check this flag. – Erki Aring Nov 29 '20 at 10:44

2 Answers2

1

Q : "How to exit endless zmq_poll when host ip address changes?"

The best approach is to never admit a piece of code that lets you loose the control of the flow of work.

TL;DR;

Accepting a code, where you realise to become powerless & ultimately dependent on some (potentially never coming) external stimulus, well, one need not be an Apollo Guidance Computer designer, yet one shall never dare to put such piece of code in Production. Willing to take a lesson on critical-systems design? Feel free to read anything available from Ms. Margaret HAMILTON, the NASA APOLLO Programme hero, who saved the crew from crashing into the Moon surface. Lifelong lessons come from the mastery of this smart & brave lady performed some 60 years ago already.


The best approach :

Design for a chance to self-adapt ( having a Darwin in mind ).

Declare all the use-cases of zmq_poll() having some stability-related control-loop latency for idle-cycles (where no events get flagged in), say 100 ms to have about a ~ 10 Hz or 10 ms to have about a ~ 100 Hz strobe for your known control-loop stability threshold, and use your idle-loop time for detecting and soft-signalling of any and all such important changes into your code, that will thus get chance to knowingly self-adapt to them per-incident.

Self-adaptation to a changed interface addresses (a live-system manual IP-address change being one such) should, as an example of good design-practice, also de-commission all so far active (now dead) .bind()-s, as these might otherwise intervene with some round-robin and fair-queue based Socket()-instances' methods, now potentially waiting infinitely on deaf ends etc.)

The list of such countermeasures would be endless here, yet the philosophy of designing non-blocking, self-adaptive code is the same.

Assume problems to be sure they will come, the only thing we do not know is, when they come, from which direction and how often we will have to bother to have to cope with them.

The rest is yours :o)

halfer
  • 19,824
  • 17
  • 99
  • 186
user3666197
  • 1
  • 6
  • 50
  • 92
1

What you need is a control mechanism that causes zmq_poll() to return when a poll items reconfiguration is required.

First create a poll control socket:

void *poll_ctrl = zmq_socket (context, ZMQ_PAIR);
zmq_bind (poll_ctrl, "inproc://poll_control");

Now modify your poll loop to include the poll_ctrl socket:

while(1) {
    zmq_msg_t message;
    zmq_pollitem_t items [] = {
            { frontend1, 0, ZMQ_POLLIN, 0 },
            { backend1,  0, ZMQ_POLLIN, 0 },
            { poll_ctrl, 0, ZMQ_POLLIN, 0 },
    };
    zmq_poll (items, 3, -1);
    if(items[0].revents & ZMQ_POLLIN) {
     ...
    }
    if(items[1].revents & ZMQ_POLLIN) {
     ...
    }
    if(items[2].revents & ZMQ_POLLIN) {
     // read command and loop
     char cmd [4] = { 0 };
     int size = zmq_recv (items[2].socket, cmd, sizeof(cmd) - 1, 0);
     if (size > 0)
      buffer[size < sizeof(cmd) ? size : sizeof(cmd) - 1] = '\0';
     // more processing can be done here based on command if necessary
    }
}

Now create a function to trigger the zmq_poll() to return when the ip has changed:

void reconfigure_poll() {
    void *ctrl = zmq_socket (context, ZMQ_PAIR);
    zmq_connect (ctrl, "inproc://poll_control");
    zmq_send (ctrl, "CFG", 3, );
    zmq_close (ctrl);
}

The mechanism is thread safe.

BitByteDog
  • 3,074
  • 2
  • 26
  • 39