diff --git a/httperf/AUTHORS b/httperf/AUTHORS index be97e85..58f101a 100755 --- a/httperf/AUTHORS +++ b/httperf/AUTHORS @@ -10,6 +10,7 @@ Ted Bullock compiler warning fixes gnu auto tool build system man page --wset typo fix regarding --uri + unallocated timer memory leak fix Tai Jin zero-length content fix diff --git a/httperf/ChangeLog b/httperf/ChangeLog index b317989..e827b82 100755 --- a/httperf/ChangeLog +++ b/httperf/ChangeLog @@ -1,3 +1,8 @@ +2007-07-15 Ted Bullock + + * timer.c, timer.h, httperf.c: Fixed memory leak associated with timers not being + freed + 2007-06-03 Ted Bullock * event.c and event.h: Moved to localevent.c and localevent.h for integration with diff --git a/httperf/NEWS b/httperf/NEWS index d4a8959..b2cc3fb 100755 --- a/httperf/NEWS +++ b/httperf/NEWS @@ -1,3 +1,6 @@ +* New in version 1.0: +** timer memory leak fix (Ted Bullock) + * New in version 0.9: ** Re-Factored build system now builds on the following platforms HP-UX 11i (64-bit PA-RISC and IA-64) diff --git a/httperf/src/httperf.c b/httperf/src/httperf.c index 5ebcabf..4c5356a 100755 --- a/httperf/src/httperf.c +++ b/httperf/src/httperf.c @@ -1056,5 +1056,8 @@ main (int argc, char **argv) for (i = 0; i < num_stats; ++i) (*stat[i]->dump)(); + timer_reset_all(); + timer_free_all(); + return 0; } diff --git a/httperf/src/timer.c b/httperf/src/timer.c index 44db8b4..93b8484 100755 --- a/httperf/src/timer.c +++ b/httperf/src/timer.c @@ -43,13 +43,17 @@ #define WHEEL_SIZE 4096 -#if 1 static Time now; -#endif static Time next_tick; static Timer *timer_free_list = 0; static Timer *t_curr = 0; +static struct Timer_List { + struct Timer_List *next; + struct Timer *this_timer; + +} *timer_list_head = NULL; + /* * What a wheel is made of, no? */ @@ -90,6 +94,50 @@ timer_init(void) curr = wheel; } +static void +timer_free_memory(struct Timer_List *node) +{ + + if (node) { + if (node->next) + timer_free_memory(node->next); + + memset(node->this_timer, 0, sizeof(struct Timer)); + free(node->this_timer); + + memset(node, 0, sizeof(struct Timer_List)); + free(node); + } +} + +void +timer_reset_all(void) +{ + Timer *t, *t_next; + + for (t = curr->next; t; t = t_next) { + (*t->func) (t, t->arg); + t_next = t->q.next; + + /* + * Push timer into timer_free_list for later re-use + */ + done(t); + } + + timer_init(); +} + +void +timer_free_all(void) +{ + timer_free_memory(timer_list_head); + timer_free_list = NULL; + timer_list_head = NULL; + + timer_init(); +} + void timer_tick(void) { @@ -100,10 +148,17 @@ timer_tick(void) now = timer_now_forced(); while (timer_now() >= next_tick) { + /* + * Check for timers that have timed out and expire them + */ for (t = curr->next; t && t->delta == 0; t = t_next) { t_curr = t; (*t->func) (t, t->arg); t_next = t->q.next; + + /* + * Push timer into timer_free_list for later re-use + */ done(t); } t_curr = 0; @@ -131,12 +186,23 @@ timer_schedule(Timer_Callback timeout, Any_Type arg, Time delay) t = timer_free_list; timer_free_list = t->q.next; } else { + struct Timer_List *node = malloc(sizeof(struct Timer_List)); + if (!node) { + fprintf(stderr, "%s.timer_schedule: %s\n", + prog_name, strerror(errno)); + return 0; + } + t = malloc(sizeof(*t)); if (!t) { fprintf(stderr, "%s.timer_schedule: %s\n", prog_name, strerror(errno)); return 0; } + + node->this_timer = t; + node->next = timer_list_head; + timer_list_head = node; } memset(t, 0, sizeof(*t)); t->func = timeout; diff --git a/httperf/src/timer.h b/httperf/src/timer.h index 58f0b14..3b8717d 100755 --- a/httperf/src/timer.h +++ b/httperf/src/timer.h @@ -64,6 +64,8 @@ extern Time timer_now_forced (void); extern Time timer_now (void); extern void timer_init (void); +extern void timer_reset_all(void); +extern void timer_free_all(void); /* Needs to be called at least once every TIMER_INTERVAL: */ extern void timer_tick (void);