Re: [PATCH] target/riscv: Fix memory leak in riscv_trigger_unrealize()

Philippe Mathieu-Daudé <[email protected]> Thu, 23 Jul 2026 13:35:56 +0200
Newsgroups org.nongnu.qemu-riscv,org.nongnu.qemu-devel
Message-ID <[email protected]>
On 23/7/26 13:12, Daniel Henrique Barboza wrote:
> 
> 
> On 7/23/2026 6:59 AM, Zeng Chi wrote:
>> From: Zeng Chi <[email protected]>
>>
>> In riscv_trigger_unrealize(), the per-trigger QEMUTimer objects are
>> created in riscv_trigger_realize() using timer_new_ns().  However,
>> unrealize only calls timer_del() to cancel them, but never frees the
>> timer objects themselves. This results in a memory leak every time a
>> CPU instance is unrealized (e.g., during hot-unplug or machine teardown).
>>
>> Fix it by calling timer_free() for each timer after timer_del().
> 
> I made the assumption that timer_del() calls g_free() under the hood.  
> Seems
> like the best assumption is always to not make assumptions ...

Same, I always gets confused by that method. I once asked on IRC whether
to rename timer_del() to timer_cancel() or not but don't remember the
outcome of the discussion, I suppose there was a reason for not doing
the mechanical change, like "delete" is the appropriate action to cancel
a timer?

> 
>>
>> Fixes: 820552a92e32 ("target/riscv: dynamic alloc of debug trigger 
>> arrays")
>> Signed-off-by: Zeng Chi <[email protected]>
>> ---
> 
> Reviewed-by: Daniel Henrique Barboza <[email protected]>
> 
>>   target/riscv/tcg/debug.c | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/target/riscv/tcg/debug.c b/target/riscv/tcg/debug.c
>> index 3c0fe70101..ffbdc17023 100644
>> --- a/target/riscv/tcg/debug.c
>> +++ b/target/riscv/tcg/debug.c
>> @@ -1081,6 +1081,7 @@ void riscv_trigger_unrealize(CPURISCVState *env)
>>       for (int i = 0; i < env->num_triggers; i++) {
>>           timer_del(env->itrigger_timer[i]);
>> +        timer_free(env->itrigger_timer[i]);

timer_free() also cancel/delete the timer. Could we simply replace
timer_del() -> timer_free()?

>>       }
>>       g_free(env->itrigger_timer);
>>   }
> 
>