[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] Infinity loop



.. and that assumption - that a freshly allocated event is
somehow always zero'ed out - is completely bogus.

I hate to ask, as someone who for the most part lurks and writes
a lot of networking software - how the heck are people designing
applications which fail so badly at assumptions, like not guarantee'ing
event_set() occurs once? :)



Adrian

On Mon, Oct 05, 2009, nicolas dumont wrote:
> Hello
> 
> I've had the same behaviour, exactly in same function event_active()
> 
> It was due to the fact that I ran event_set() after doing event_add() of 
> the same event.
> In that case, the internal flags are resetted by the event_set().
> Then the event state is lost and can't be deleted,
> and because there's not trap for that in libevent code, you fall in 
> infinite loop.
> 
> The only solution I found, in order to be sure that I won't fall into 
> this infinite loop.
> ( And because I use a lot of events, and that was to complex to rewrite 
> all the events architecture of my software)
> 
> Is to patch the event_set() and run event_del()at the beginning of 
> event_set like this :
> 
> event_set(struct event *ev, int fd, short events,
> void (*callback)(int, short, void *), void *arg)
> {
> + if ((ev->ev_flags & EVLIST_DEL_ALL) != 0 )
> + {
> + event_debug(("event_set: ev %p,ev_flags 0x%X call event_del(), ev is 
> not correctly initialized",
> + ev,ev->ev_flags));
> + event_del(ev);
> + assert((ev->ev_flags & EVLIST_DEL_ALL) == 0);
> + }
> +
> 
> with :
> +#define EVLIST_DEL_ALL (EVLIST_TIMEOUT|EVLIST_INSERTED|EVLIST_ACTIVE)
> 
> 
> But, be careful with that solution !!!
> It implies to initialize to 0 the struct event before doing the first 
> event_set() !!!!
> 
> Here is a copy of the mail I've sent to libevent mailing list :
> 
> 
> >Hi,
> >
> >I'm using events in 1.4.12-stable.
> >
> >Sometimes, my daemon, which uses event_base_loop()
> >goes in an infinite loop ( verbose traces below ).
> >
> >This infinite loop is inside function event_process_active() which
> >calls event_del() with ev_flags=0x80 ( =EVLIST_INIT)
> >This flags is not managed by event_del(), then the ev is never deleted
> >from the queue, then the loop "for" retries again and again.
> >
> >static void event_process_active(struct event_base *base)
> >{
> >...
> > for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
> > if (ev->ev_events & EV_PERSIST)
> > event_queue_remove(base, ev, EVLIST_ACTIVE);
> > else
> > event_del(ev);
> >...
> > }
> >}
> >
> >
> >[2009-08-26 17:12:29] ev : event_add: event: 0xb13a7e0, EV_READ
> >call 0x280b789c
> >[2009-08-26 17:12:29] ev : kq_insert: fd 43 EVFILT_READ
> >[2009-08-26 17:12:29] ev : event_queue_insert queue=0x2 ev_flags=0x1082
> >[2009-08-26 17:12:29] ev : event_process_active: call event_del
> >[2009-08-26 17:12:29] ev : event_del: 0xb13e6a0, callback 0x280b7dd4,
> >ev_flags 0x1082 ev_events 0x2
> >[2009-08-26 17:12:29] ev : event_queue_remove queue=0x2 ev_flags=0x1080
> >[2009-08-26 17:12:29] ev : kq_insert: fd 74 EVFILT_READ (del)
> >[2009-08-26 17:12:29] ev : event_process_active: call event_del
> >[2009-08-26 17:12:29] ev : event_del: 0xb13e6a0, callback 0x280b7dd4,
> >ev_flags 0x80 ev_events 0x2
> >[2009-08-26 17:12:29] ev : event_process_active: call event_del
> >[2009-08-26 17:12:29] ev : event_del: 0xb13e6a0, callback 0x280b7dd4,
> >ev_flags 0x80 ev_events 0x2
> >[2009-08-26 17:12:29] ev : event_process_active: call event_del
> >[2009-08-26 17:12:29] ev : event_del: 0xb13e6a0, callback 0x280b7dd4,
> >ev_flags 0x80 ev_events 0x2
> >[2009-08-26 17:12:29] ev : event_process_active: call event_del
> >[2009-08-26 17:12:29] ev : event_del: 0xb13e6a0, callback 0x280b7dd4,
> >ev_flags 0x80 ev_events 0x2
> >[2009-08-26 17:12:29] ev : event_process_active: call event_del
> >[2009-08-26 17:12:29] ev : event_del: 0xb13e6a0, callback 0x280b7dd4,
> >ev_flags 0x80 ev_events 0x2
> >.....
> >....
> >...
> >..
> >.
> >
> >After investigating my code, I found that I call in this order :
> >
> >event_set(&ev, EV_READ,callback_one);
> >event_add(&ev);
> >
> >and later :
> >event_set(&ev, EV_READ,callback_two);
> >
> >The pb is that the second event_set which is called to set another 
> callback resets the ev->flags with EVLIST_INIT
> >After that I fall into the infinite loop describe behind.
> >
> >So, even if I'm doing something wrong with the usage of the API, it 
> should not go in an infinite loop.
> >
> >Finnaly, to prevent to go in the infinite loop ,
> >do I have to run event_del(&ev) each time before using event_set(&ev) ?
> >
> >Thank's a lot for your answer.
> 
> 
> Hereafter is the answer from libevnet team :
> 
> >This is exactly so.  You can't call event_set or event_assign on an
> >event while it is added.
> >
> >Unfortunately, because event_set works on uninitialized memory, there
> >is no way for it to check whether it's looking at an added event, or a
> >random chunk of memory that happens to have bits set in the right
> >place.
> 
> 
> 
> Best regards,
> Nicolas Dumont.
> 
> -- 
> Nicolas Dumont
> System Team Leader
> 
> NETASQ - We secure IT
> 3 rue Archimede
> 59650 Villeneuve d'Ascq
> France
> Tel :  +33 (0)3.20.61.90.44
> Fax :  +33 (0)3.20.61.97.48 
> 



-- 
- Xenion - http://www.xenion.com.au/ - VPS Hosting - Commercial Squid Support -
- $24/pm+GST entry-level VPSes w/ capped bandwidth charges available in WA -
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.