Change flush_events() to expire_events().
authorGuus Sliepen <guus@tinc-vpn.org>
Mon, 19 Jan 2009 21:50:05 +0000 (22:50 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Mon, 19 Jan 2009 21:50:05 +0000 (22:50 +0100)
The former function made a totally bogus shallow copy of the event_tree, called
the handler of each event and then deleted the whole tree.  This should've
caused tinc to crash when an ALARM signal was sent more than once, but for some
reason it didn't. It also behaved incorrectly when a handler added a new event.

The new function just moves the expiration time of all events to the past.

src/event.c
src/event.h
src/net.c

index 8a63e12d39fa4d598f8daef9b51016e3d87a9466..5df052772dbf4d691bad0b7d61b38f7681314d40 100644 (file)
@@ -47,7 +47,7 @@ void init_events(void)
 {
        cp();
 
-       event_tree = avl_alloc_tree((avl_compare_t) event_compare, NULL);
+       event_tree = avl_alloc_tree((avl_compare_t) event_compare, (avl_action_t) free_event);
 }
 
 void exit_events(void)
@@ -57,26 +57,32 @@ void exit_events(void)
        avl_delete_tree(event_tree);
 }
 
-void flush_events(void)
+void expire_events(void)
 {
-       avl_tree_t *to_flush;
+       avl_node_t *node;
        event_t *event;
+       time_t diff;
 
        /*
-        * Events can be inserted from event handlers, so only flush events
-        * already in the priority queue.
+        * Make all events appear expired by substracting the difference between
+         * the expiration time of the last event and the current time.
         */
 
        cp();
 
-       to_flush = event_tree;
-       init_events();
-       while (to_flush->head) {
-               event = to_flush->head->data;
-               event->handler(event->data);
-               avl_delete(to_flush, event);
+       if(!event_tree->tail)
+               return;
+
+       event = event_tree->tail->data;
+       if(event->time < now)
+               return;
+
+       diff = 1 + event->time - now;
+       
+       for(node = event_tree->head; node; node = node->next) {
+               event = node->data;
+               event->time -= diff;
        }
-       avl_delete_tree(to_flush);
 }
 
 event_t *new_event(void)
@@ -118,7 +124,7 @@ event_t *get_expired_event(void)
                event = event_tree->head->data;
 
                if(event->time < now) {
-                       event_del(event);
+                       avl_unlink_node(event_tree, event_tree->head);
                        return event;
                }
        }
index 6f4973f0bc30e10f033933cd97ca44c2cec6deca..2280e4cc958e18d6638c55723e43de01b0b7587a 100644 (file)
@@ -38,7 +38,7 @@ typedef struct {
 
 extern void init_events(void);
 extern void exit_events(void);
-extern void flush_events(void);
+extern void expire_events(void);
 extern event_t *new_event(void) __attribute__ ((__malloc__));
 extern void free_event(event_t *);
 extern void event_add(event_t *);
index 9e4829a35b75fcefba7eaaab3d044db8c2071d00..1de5f1fb711530eff4420f212062ef26424e06bc 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -423,18 +423,17 @@ int main_loop(void)
                        }
                }
 
+               if(sigalrm) {
+                       logger(LOG_INFO, _("Flushing event queue"));
+                       expire_events();
+                       sigalrm = false;
+               }
 
                while((event = get_expired_event())) {
                        event->handler(event->data);
                        free_event(event);
                }
 
-               if(sigalrm) {
-                       logger(LOG_INFO, _("Flushing event queue"));
-                       flush_events();
-                       sigalrm = false;
-               }
-
                if(sighup) {
                        connection_t *c;
                        avl_node_t *node;