diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-06-04 18:18:05 -0300 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-06-04 19:17:36 -0300 |
| commit | fa20c1f8f4e094abe0169d39fce8181bc26d6dab (patch) | |
| tree | a0bec0441058e746cc216e87c6b570b4e9638154 | |
| parent | 1e7921d7227de5da0dfc167943092c823ec7e49b (diff) | |
| download | linux-fa20c1f8f4e094abe0169d39fce8181bc26d6dab.tar.gz linux-fa20c1f8f4e094abe0169d39fce8181bc26d6dab.zip | |
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>
| -rw-r--r-- | tools/perf/builtin-sched.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 4aa7833cae6e..7bd61028327b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -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); } } |
