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

Re: [Libevent-users] Infinity loop



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

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature