perf sched: Fix thread reference leaks in timehist_get_thread()

timehist_get_thread() acquires a thread reference via
machine__findnew_thread() and an idle thread reference via
get_idle_thread() (which calls thread__get()).  Two error paths in
the idle_hist block return NULL without releasing these references:

 - When get_idle_thread() fails, the thread reference leaks.
 - When thread__priv(idle) returns NULL, both idle and thread leak.

Additionally, the idle thread reference acquired on the success path
is never released, leaking a reference on every sample when
--idle-hist is active.

Add thread__put() calls on both error paths and release the idle
reference after use on the success path.

Fixes: 5d8f17fb5822 ("perf sched timehist: Add -I/--idle-hist option")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2026-06-04 18:18:05 -03:00
parent 1e7921d722
commit fa20c1f8f4

View File

@ -2546,12 +2546,16 @@ static struct thread *timehist_get_thread(struct perf_sched *sched,
idle = get_idle_thread(sample->cpu);
if (idle == NULL) {
pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu);
thread__put(thread);
return NULL;
}
itr = thread__priv(idle);
if (itr == NULL)
if (itr == NULL) {
thread__put(idle);
thread__put(thread);
return NULL;
}
thread__put(itr->last_thread);
itr->last_thread = thread__get(thread);
@ -2559,6 +2563,8 @@ static struct thread *timehist_get_thread(struct perf_sched *sched,
/* copy task callchain when entering to idle */
if (perf_sample__intval(sample, "next_pid") == 0)
save_idle_callchain(sched, itr, sample);
thread__put(idle);
}
}