[Libevent-users] multiple calls of event_dispatch()

Scott Lamb slamb at slamb.org
Mon Feb 26 18:56:01 EST 2007


On Feb 26, 2007, at 2:57 PM, Christian Ress wrote:

> Hello,
>
> I stumbled across libevent and it seems to fit my needs very well.
> However, I wonder if this is side-effect free:
>
> second_cb(..) { .. }
> first_cb(..) {
>   ..
>   struct event newev;
>   evtimer_set(&newev, second_cb, NULL);
>   event_base_set(ev_base, &newev);
>   event_add(&newev, &tv);
>
>   event_base_dispatch(ev_base);
> }
>
> main() {
>   ..
>   ev_base = event_init();
>   evtimer_set(ev, first_cb, NULL);
>   event_add(ev, &tv);
>
>   event_base_dispatch(ev_base);
> }
>
> The point of this is creating new events 'on demand', but since I'm  
> calling event_dispatch when being called by event_loop, I wonder if  
> this might lead to recursion issues or similar bad behaviour.
>
> I hope someone can clarify this :)

First, keep in mind something that tripped up me when I first started  
using libevent - the "struct event" you pass to event_add is not  
duplicated, but rather directly linked into the event_base's queues.  
So if it's a timeout, it needs to live until it fires (or forever  
with EV_PERSIST) or you manually call event_del(). There are a lot of  
reasons that might not happen in the next invocation of  
event_base_dispatch(), so this code seems dangerous.

And second...while I don't see anything off-hand in libevent that  
would break based on this recursion, I don't think it was intended to  
be used that way, and you always risk stack overflows if you don't  
have a way to bound your recursion.

You can create new events 'on demand' with event_once. Which isn't  
magic - it just internally allocates a new struct event on the heap  
that adds a callback which - after calling your callback - frees the  
struct event. You could accomplish the same thing yourself:

void
first_cb(int fd, short events, void *arg)
{
     struct event *newev;
     int res;

     ...

     newev = malloc(sizeof(struct event));
     ...newev == NULL error handling goes here...
     evtimer_set(newev, ...);
     res = event_add(&newev, &tv);
     ...event_add error handling goes here...
}

void
second_cb(int fd, short events, void *arg)
{
     struct event *myev = arg;

     ...
     free(myev);
}

-- 
Scott Lamb <http://www.slamb.org/>




More information about the Libevent-users mailing list