[Olsr-dev] [PATCH v1 1/2] scheduler: mark timers for removal and only remove them in a cleanup walk
Ferry Huberts
(spam-protected)
Mon Feb 29 15:23:59 CET 2016
From: Ferry Huberts <(spam-protected)>
Fixes crashes in networks with many nodes.
*** olsr.org - pre-0.9.1-git_dd7c5a0-hash_b9729ef932ee0c718b5da79dcf6a5fce ***
Build date: 2016-02-24 21:02:23 on jenkins
http://www.olsr.org
/usr/sbin/olsrd (olsr_segv_handler) src/main.c:323
/lib/i386-linux-gnu/libc.so.6 (+0x2de78) [0xb760ce78]
/usr/sbin/olsrd (list_remove) src/common/list.c:105
/usr/sbin/olsrd (olsr_stop_timer) src/scheduler.c:874
/usr/sbin/olsrd (olsr_del_nbr2_list) src/neighbor_table.c:85
/usr/sbin/olsrd (olsr_delete_neighbor_table) src/neighbor_table.c:211
/usr/sbin/olsrd (olsr_delete_link_entry) src/link_set.c:375
/usr/sbin/olsrd (olsr_expire_link_entry) src/link_set.c:495
/usr/sbin/olsrd (walk_timers) src/scheduler.c:650
/usr/sbin/olsrd (olsr_scheduler) src/scheduler.c:506
/usr/sbin/olsrd (main) src/main.c:705
olsrd crashed, stack trace follows
/usr/sbin/olsrd (olsr_segv_handler) src/main.c:323
/lib/i386-linux-gnu/libc.so.6 (+0x2de78) [0xb764ce78]
/usr/sbin/olsrd (list_remove) src/common/list.c:105
/usr/sbin/olsrd (olsr_stop_timer) src/scheduler.c:874
/usr/sbin/olsrd (olsr_update_gateway_entry) src/gateway.c:1208
/usr/sbin/olsrd (olsr_input_hna) src/hna_set.c:446
/usr/sbin/olsrd (parse_packet) src/parser.c:393
/usr/sbin/olsrd (olsr_input) src/parser.c:496
/usr/sbin/olsrd (poll_sockets) src/scheduler.c:341
/usr/sbin/olsrd (olsr_scheduler) src/scheduler.c:499
/usr/sbin/olsrd (main) src/main.c:705
Signed-off-by: Ferry Huberts <(spam-protected)>
---
src/scheduler.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
src/scheduler.h | 1 +
2 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/src/scheduler.c b/src/scheduler.c
index cf8968a..062c96e 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -47,6 +47,7 @@
#include "net_os.h"
#include "mpr_selector_set.h"
#include "olsr_random.h"
+#include "common/avl.h"
#include <sys/times.h>
@@ -74,8 +75,44 @@ static struct list_node socket_head = { &socket_head, &socket_head };
/* Prototypes */
static void walk_timers(uint32_t *);
+static void walk_timers_cleanup(void);
static void poll_sockets(void);
static uint32_t calc_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val);
+static void olsr_cleanup_timer(struct timer_entry *timer);
+
+struct avl_tree timer_cleanup_tree;
+
+struct timer_cleanup_entry {
+ struct avl_node avl;
+ struct timer_entry * timer;
+};
+
+/* static inline struct timer_cleanup_entry * node2timercleanup(struct avl_node *ptr) */
+AVLNODE2STRUCT(node2timercleanup, struct timer_cleanup_entry, avl);
+
+/**
+ * Loop over all timer cleanup entries and put the iterated entry in timer
+ */
+#define OLSR_FOR_ALL_TIMERS_CLEANUP(timer) \
+{ \
+ struct avl_node *timer_avl_node, *timer_avl_node_next; \
+ for (timer_avl_node = avl_walk_first(&timer_cleanup_tree); \
+ timer_avl_node; timer_avl_node = timer_avl_node_next) { \
+ timer_avl_node_next = avl_walk_next(timer_avl_node); \
+ timer = node2timercleanup(timer_avl_node);
+#define OLSR_FOR_ALL_TIMER_CLEANUP_END(timer) }}
+
+static int avl_comp_timer(const void *entry1, const void *entry2) {
+ if (entry1 < entry2) {
+ return -1;
+ }
+
+ if (entry1 > entry2) {
+ return -1;
+ }
+
+ return 0;
+}
/*
* A wrapper around times(2). Note, that this function has some
@@ -504,6 +541,7 @@ void olsr_scheduler(void)
/* Process timers */
walk_timers(&timer_last_run);
+ walk_timers_cleanup();
if (state != RUNNING) {
break;
@@ -530,6 +568,7 @@ void olsr_scheduler(void)
/* Read incoming data and handle it immediiately */
handle_fds(next_interval);
}
+ walk_timers_cleanup();
state = ENDED;
}
@@ -583,6 +622,8 @@ olsr_init_timers(void)
last_tv = first_tv;
now_times = olsr_times();
+ avl_init(&timer_cleanup_tree, avl_comp_timer);
+
for (idx = 0; idx < TIMER_WHEEL_SLOTS; idx++) {
list_head_init(&timer_wheel[idx]);
}
@@ -638,6 +679,10 @@ walk_timers(uint32_t * last_run)
list_add_after(&tmp_head_node, timer_node);
timers_walked++;
+ if (timer->timer_flags & OLSR_TIMER_REMOVED) {
+ continue;
+ }
+
/* Ready to fire ? */
if (TIMED_OUT(timer->timer_clock)) {
@@ -694,6 +739,16 @@ walk_timers(uint32_t * last_run)
*last_run = now_times;
}
+static void walk_timers_cleanup(void) {
+ struct timer_cleanup_entry * timer;
+
+ OLSR_FOR_ALL_TIMERS_CLEANUP(timer) {
+ olsr_cleanup_timer(timer->timer);
+ avl_delete(&timer_cleanup_tree, &timer->avl);
+ free(timer);
+ } OLSR_FOR_ALL_TIMER_CLEANUP_END(slot)
+}
+
/**
* Stop and delete all timers.
*/
@@ -711,6 +766,7 @@ olsr_flush_timers(void)
olsr_stop_timer(list2timer(timer_head_node->next));
}
}
+ walk_timers_cleanup();
}
/**
@@ -858,7 +914,8 @@ void
olsr_stop_timer(struct timer_entry *timer)
{
/* It's okay to get a NULL here */
- if (!timer) {
+ if (!timer //
+ || (timer->timer_flags & OLSR_TIMER_REMOVED)) {
return;
}
@@ -868,11 +925,45 @@ olsr_stop_timer(struct timer_entry *timer)
timer->timer_cookie->ci_name, timer, timer->timer_cb_context);
+ timer->timer_flags &= ~OLSR_TIMER_RUNNING;
+ timer->timer_flags |= OLSR_TIMER_REMOVED;
+
+ {
+ struct timer_cleanup_entry * node = olsr_malloc(sizeof(struct timer_cleanup_entry), "timer cleanup entry");
+ node->avl.key = timer;
+ node->timer = timer;
+ if (avl_insert(&timer_cleanup_tree, &node->avl, AVL_DUP_NO) == -1) {
+ /* duplicate */
+ free(node);
+ }
+ }
+}
+
+/**
+ * Clean up a timer.
+ *
+ * @param timer the timer_entry that shall be cleaned up
+ */
+static void
+olsr_cleanup_timer(struct timer_entry *timer)
+{
+ /* It's okay to get a NULL here */
+ if (!timer //
+ || !(timer->timer_flags & OLSR_TIMER_REMOVED)) {
+ return;
+ }
+
+ assert(timer->timer_cookie); /* we want timer cookies everywhere */
+
+ OLSR_PRINTF(7, "TIMER: cleanup %s timer %p, ctx %p\n",
+ timer->timer_cookie->ci_name, timer, timer->timer_cb_context);
+
+
/*
* Carve out of the existing wheel_slot and free.
*/
list_remove(&timer->timer_list);
- timer->timer_flags &= ~OLSR_TIMER_RUNNING;
+ timer->timer_flags &= ~OLSR_TIMER_REMOVED;
olsr_cookie_usage_decr(timer->timer_cookie->ci_id);
olsr_cookie_free(timer_mem_cookie, timer);
diff --git a/src/scheduler.h b/src/scheduler.h
index a18198b..6afc791 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -90,6 +90,7 @@ LISTNODE2STRUCT(list2timer, struct timer_entry, timer_list);
/* Timer flags */
#define OLSR_TIMER_RUNNING ( 1 << 0) /* this timer is running */
+#define OLSR_TIMER_REMOVED ( 1 << 1) /* this timer is tagged for removal */
/* Timers */
void olsr_init_timers(void);
--
2.5.0
More information about the Olsr-dev
mailing list