Currently timer_free() is a simple wrapper for g_free(). This means that the timer being freed must not be currently active, as otherwise QEMU might crash later when the active list is processed and still has a pointer to freed memory on it. As a result almost all calls to timer_free() are preceded by a timer_del() call, as can be seen in the output of git grep -B1 '\<timer_free\>'
This is unfortunate API design as it makes it easy to accidentally misuse (by forgetting the timer_del()), and the correct use is annoyingly verbose. Make timer_free() imply a timer_del(). We use the same check as timer_deinit() ("ts->expire_time == -1") to determine whether the timer is already deleted (although this is only saving the effort of re-iterating through the active list, as timer_del() on an already-deactivated timer is safe). Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> --- include/qemu/timer.h | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index bdecc5b41fe..1789a600525 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -609,17 +609,6 @@ static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb, */ void timer_deinit(QEMUTimer *ts); -/** - * timer_free: - * @ts: the timer - * - * Free a timer (it must not be on the active list) - */ -static inline void timer_free(QEMUTimer *ts) -{ - g_free(ts); -} - /** * timer_del: * @ts: the timer @@ -631,6 +620,22 @@ static inline void timer_free(QEMUTimer *ts) */ void timer_del(QEMUTimer *ts); +/** + * timer_free: + * @ts: the timer + * + * Free a timer. This will call timer_del() for you to remove + * the timer from the active list if it was still active. + */ +static inline void timer_free(QEMUTimer *ts) +{ + + if (ts->expire_time != -1) { + timer_del(ts); + } + g_free(ts); +} + /** * timer_mod_ns: * @ts: the timer -- 2.20.1