diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-06-05 11:12:08 -0300 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-06-05 19:17:31 -0300 |
| commit | cda5a94ad9181cd60cbf04be11d524201bf489a2 (patch) | |
| tree | ebdfdf002581e85ce8e456250b8338f46351767e | |
| parent | 5fb2e6ad8c5d6b3b380f94c7456595511f3731be (diff) | |
| download | linux-cda5a94ad9181cd60cbf04be11d524201bf489a2.tar.gz linux-cda5a94ad9181cd60cbf04be11d524201bf489a2.zip | |
perf sched: Clean up idle_threads entry on init failure
get_idle_thread() allocates a thread via thread__new() and stores it in
idle_threads[cpu], then calls init_idle_thread() to set up the private
data. If init_idle_thread() fails (e.g. OOM for the idle_thread_runtime
struct), the function returns NULL but leaves the partially initialized
thread in idle_threads[cpu].
On subsequent calls for the same CPU, get_idle_thread() finds a non-NULL
idle_threads[cpu], skips allocation, and returns thread__get() on a
thread that has no priv data. Callers then get a thread whose
thread__priv() returns NULL, leading to unexpected behavior.
Release the thread and reset the slot to NULL on init failure so the
entry doesn't persist in a corrupted state.
Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
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 | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 21fb820b625b..e4378cc9ab3e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2514,8 +2514,11 @@ static struct thread *get_idle_thread(int cpu) idle_threads[cpu] = thread__new(0, 0); if (idle_threads[cpu]) { - if (init_idle_thread(idle_threads[cpu]) < 0) + if (init_idle_thread(idle_threads[cpu]) < 0) { + /* clean up so next call doesn't find a half-initialized thread */ + thread__zput(idle_threads[cpu]); return NULL; + } } } |
