zmq_poll workaround

This issue is fixed in ØMQ/2.1.0 and later. The workaround below is needed only for 2.0.x versions of ØMQ

When you call zmq_poll with a timeout it has the unfortunate tendency to return before the timeout completes, and without any socket activity. Here is a workaround wrapper written by Thomas Guyot-Sionnest <moc.liamg|toyugt#moc.liamg|toyugt> aka 'dermoth' that shows how to use timers to get a poll that works:

/* wrapper around zmq_poll which may return zero without reaching the
 * specified timeout */
int
my_zmqpoll (zmq_pollitem_t *items, const int nitems, const long timeout)
{
    struct timeval tv, te;
    int rc, ret;
    long tmleft;

    /* Populate te with timeout value */
    te.tv_sec  = timeout / 1000000;
    te.tv_usec = timeout - (te.tv_sec * 1000000);

    rc = gettimeofday (&tv, NULL);
    assert (rc == 0);

    /* Add current time to the timeout (end time) */
    te.tv_sec  += tv.tv_sec;
    te.tv_usec += tv.tv_usec;
    te.tv_sec  += te.tv_usec / 1000000;
    te.tv_usec %= 1000000;

    /* Loop over, return either >0, or 0 after a timeout */
    tmleft = timeout;
    while (1) {
        ret = zmq_poll (items, nitems, tmleft);
        assert (ret >= 0);

        rc = gettimeofday (&tv, NULL);
        assert (rc == 0);

        if (ret == 0) {
            /* Keep on looping unless time's up */
            if (te.tv_sec <  tv.tv_sec 
            || (te.tv_sec == tv.tv_sec && te.tv_usec <= tv.tv_usec))
                return ret;
            tmleft = ( (te.tv_sec - tv.tv_sec) * 1000000) + (te.tv_usec - tv.tv_usec);
        } 
        else
            return ret;
    }
}

Thomas has released this code to the public domain.

Comments: 10

Add a New Comment