zloop gets confused if you create timer with same arg as expired timer #114

Closed
hintjens opened this Issue Jan 14, 2013 · 4 comments

Comments

Projects
None yet
1 participant
Owner

hintjens commented Jan 14, 2013

Problem: if a timer expires (either by default, or by calling zloop_timer_end(), and you add a new timer with the same argument, zloop will destroy the new timer at the same time as it destroys the expired one.

Solution: when reaping zombie timers, only reap the first one. Secondly, add new timers to end of timer list, not start.

Owner

hintjens commented Jan 14, 2013

Test case:

/*
This test exposes a problem with timer handling in zloop whereby
an attempt to replace an old timer with a new one in a socket
event handler does not succeed.

The test below initialises a timer which should be replaced (before
it expired) when the reactor calls s_socket_event.

However, what happens instead is that the new timer, though
added, never fires.

The problem does not occur if the original timer is not deleted,
in which case, both timers fire at the correct time.

Compile: gcc -o timer timer.c -I/usr/local/include -lczmq -lzmq

*/

#include "czmq.h"

static int
s_fire_timer (zloop_t *loop, zmq_pollitem_t *item, void *arg)
{
    printf ("Timer %p fired!\n", arg);
    return 0;
}

static int
s_socket_event (zloop_t *loop, zmq_pollitem_t *item, void *arg)
{
    zmsg_t *msg = zmsg_recv (item->socket);
    zmsg_destroy (&msg);
    printf ("Replacing timer with arg %p\n", item->socket);
    zloop_timer_end (loop, item->socket);

    // Adding a new timer with the same arg as the old one.
    // This will never fire!
    zloop_timer (loop, 1000, 1, s_fire_timer, item->socket);
    return 0;
}

int
zloop_test (bool verbose)
{
    int rc = 0;

    zctx_t *ctx = zctx_new ();
    assert (ctx);

    void *output = zsocket_new (ctx, ZMQ_PAIR);
    assert (output);
    rc = zsocket_bind (output, "inproc://timer.test");
    assert (rc == 0);
    void *input = zsocket_new (ctx, ZMQ_PAIR);
    assert (input);

    rc = zsocket_connect (input, "inproc://timer.test");
    assert (rc == 0);

    zloop_t *loop = zloop_new ();

    assert (loop);
    zloop_set_verbose (loop, verbose);

    //  Create a timer which we're going to *try* to replace
    // in the socket handler... (but it won't get replaced,
    // and will fire eventually!)
    printf ("Creating timer with arg %p\n", input);
    zloop_timer (loop, 5000, 1, s_fire_timer, input);

    zmq_pollitem_t poll_input = { input, 0, ZMQ_POLLIN };
    rc = zloop_poller (loop, &poll_input, s_socket_event, input);
    assert (rc == 0);

    // Send a message to trigger the handler:
    zstr_send (output, "Replace timer!");
    zloop_start (loop);
    zloop_destroy (&loop);
    assert (loop == NULL);

    zctx_destroy (&ctx);
    return 0;
}


int main( void )
{
    return zloop_test (true);
}

hintjens added a commit to hintjens/czmq that referenced this issue Feb 22, 2013

felipecruz pushed a commit that referenced this issue Feb 23, 2013

@ghost

ghost commented Nov 15, 2013

If this was fixed in 95381bf shouldn't this be closed?

@hintjens hintjens closed this Nov 15, 2013

Owner

hintjens commented Nov 15, 2013

@shancat, welcome to the CZMQ maintainers' group :-) Feel welcome to merge pull requests, close issues, and invite others to the group. This is our process: http://rfc.zeromq.org/spec:22

@ghost

ghost commented Nov 15, 2013

Wow thanks! Just happy to help :) I'll be sure to read that document
again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment