diff options
Diffstat (limited to 'src/common/timer.c')
-rw-r--r-- | src/common/timer.c | 80 |
1 files changed, 68 insertions, 12 deletions
diff --git a/src/common/timer.c b/src/common/timer.c index 7f71157ae..4f2b86a32 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -25,6 +25,7 @@ #include "common/cbasetypes.h" #include "common/db.h" #include "common/memmgr.h" +#include "common/nullpo.h" #include "common/showmsg.h" #include "common/utils.h" @@ -50,7 +51,7 @@ struct timer_interface *timer; // timers (array) static struct TimerData* timer_data = NULL; static int timer_data_max = 0; -static int timer_data_num = 0; +static int timer_data_num = 1; // free timers (array) static int* free_timer_list = NULL; @@ -87,6 +88,8 @@ struct timer_func_list { int timer_add_func_list(TimerFunc func, char* name) { struct timer_func_list* tfl; + nullpo_ret(func); + nullpo_ret(name); if (name) { for( tfl=tfl_root; tfl != NULL; tfl=tfl->next ) {// check suspicious cases @@ -255,10 +258,6 @@ int64 timer_gettick(void) { /// Adds a timer to the timer_heap static void push_timer_heap(int tid) { BHEAP_ENSURE(timer_heap, 1, 256); -#ifdef __clang_analyzer__ // Clang's static analyzer warns that BHEAP_ENSURE might set BHEAP_DATA(timer_heap) to NULL. -#include "assert.h" - assert(BHEAP_DATA(timer_heap) != NULL); -#endif // __clang_analyzer__ BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP, swap); } @@ -303,7 +302,19 @@ static int acquire_timer(void) { int timer_add(int64 tick, TimerFunc func, int id, intptr_t data) { int tid; + nullpo_retr(INVALID_TIMER, func); + tid = acquire_timer(); + if (timer_data[tid].type != 0 && timer_data[tid].type != TIMER_REMOVE_HEAP) + { + ShowError("timer_add error: wrong tid type: %d, [%d]%p(%s) -> %p(%s)\n", timer_data[tid].type, tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + Assert_retr(INVALID_TIMER, 0); + } + if (timer_data[tid].func != NULL) + { + ShowError("timer_add error: func non NULL: [%d]%p(%s) -> %p(%s)\n", tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + Assert_retr(INVALID_TIMER, 0); + } timer_data[tid].tick = tick; timer_data[tid].func = func; timer_data[tid].id = id; @@ -317,9 +328,11 @@ int timer_add(int64 tick, TimerFunc func, int id, intptr_t data) { /// Starts a new timer that automatically restarts itself (infinite loop until manually removed). /// Returns the timer's id, or INVALID_TIMER if it fails. -int timer_add_interval(int64 tick, TimerFunc func, int id, intptr_t data, int interval) { +int timer_add_interval(int64 tick, TimerFunc func, int id, intptr_t data, int interval) +{ int tid; + nullpo_retr(INVALID_TIMER, func); if (interval < 1) { ShowError("timer_add_interval: invalid interval (tick=%"PRId64" %p[%s] id=%d data=%"PRIdPTR" diff_tick=%"PRId64")\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, timer->gettick())); @@ -327,6 +340,18 @@ int timer_add_interval(int64 tick, TimerFunc func, int id, intptr_t data, int in } tid = acquire_timer(); + if (timer_data[tid].type != 0 && timer_data[tid].type != TIMER_REMOVE_HEAP) + { + ShowError("timer_add_interval: wrong tid type: %d, [%d]%p(%s) -> %p(%s)\n", timer_data[tid].type, tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + Assert_retr(INVALID_TIMER, 0); + return INVALID_TIMER; + } + if (timer_data[tid].func != NULL) + { + ShowError("timer_add_interval: func non NULL: [%d]%p(%s) -> %p(%s)\n", tid, func, search_timer_func_list(func), timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + Assert_retr(INVALID_TIMER, 0); + return INVALID_TIMER; + } timer_data[tid].tick = tick; timer_data[tid].func = func; timer_data[tid].id = id; @@ -340,22 +365,35 @@ int timer_add_interval(int64 tick, TimerFunc func, int id, intptr_t data, int in /// Retrieves internal timer data const struct TimerData* timer_get(int tid) { + Assert_retr(NULL, tid > 0); return ( tid >= 0 && tid < timer_data_num ) ? &timer_data[tid] : NULL; } /// Marks a timer specified by 'id' for immediate deletion once it expires. /// Param 'func' is used for debug/verification purposes. /// Returns 0 on success, < 0 on failure. -int timer_do_delete(int tid, TimerFunc func) { - if( tid < 0 || tid >= timer_data_num ) { - ShowError("timer_do_delete error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func)); +int timer_do_delete(int tid, TimerFunc func) +{ + nullpo_ret(func); + + if (tid < 1 || tid >= timer_data_num) { + ShowError("timer_do_delete error : no such timer [%d](%p(%s))\n", tid, func, search_timer_func_list(func)); + Assert_retr(-1, 0); return -1; } if( timer_data[tid].func != func ) { - ShowError("timer_do_delete error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func)); + ShowError("timer_do_delete error : function mismatch [%d]%p(%s) != %p(%s)\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func)); + Assert_retr(-2, 0); return -2; } + if (timer_data[tid].type == 0 || timer_data[tid].type == TIMER_REMOVE_HEAP) + { + ShowError("timer_do_delete: timer already deleted: %d, [%d]%p(%s) -> %p(%s)\n", timer_data[tid].type, tid, func, search_timer_func_list(func), func, search_timer_func_list(func)); + Assert_retr(-3, 0); + return -3; + } + timer_data[tid].func = NULL; timer_data[tid].type = TIMER_ONCE_AUTODEL; @@ -365,6 +403,11 @@ int timer_do_delete(int tid, TimerFunc func) { /// Adjusts a timer's expiration time. /// Returns the new tick value, or -1 if it fails. int64 timer_addtick(int tid, int64 tick) { + if (tid < 1 || tid >= timer_data_num) { + ShowError("timer_addtick error : no such timer [%d]\n", tid); + Assert_retr(-1, 0); + return -1; + } return timer->settick(tid, timer_data[tid].tick+tick); } @@ -383,7 +426,19 @@ int64 timer_settick(int tid, int64 tick) // search timer position ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid); if (i == BHEAP_LENGTH(timer_heap)) { - ShowError("timer_settick: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + ShowError("timer_settick: no such timer [%d](%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + Assert_retr(-1, 0); + return -1; + } + + if (timer_data[tid].type == 0 || timer_data[tid].type == TIMER_REMOVE_HEAP) { + ShowError("timer_settick error: set tick for deleted timer %d, [%d](%p(%s))\n", timer_data[tid].type, tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + Assert_retr(-1, 0); + return -1; + } + if (timer_data[tid].func == NULL) { + ShowError("timer_settick error: set tick for timer with wrong func [%d](%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + Assert_retr(-1, 0); return -1; } @@ -438,6 +493,7 @@ int do_timer(int64 tick) default: case TIMER_ONCE_AUTODEL: timer_data[tid].type = 0; + timer_data[tid].func = NULL; if (free_timer_list_pos >= free_timer_list_max) { free_timer_list_max += 256; RECREATE(free_timer_list,int,free_timer_list_max); |