From 44f8dd1ee1d55db399a443e1715cd8cdd3268362 Mon Sep 17 00:00:00 2001 From: Aaron Tomlin Date: Thu, 6 Aug 2026 11:39:24 -0400 Subject: [PATCH] perf sched: Handle missing trace samples in pipe mode For pipe mode streams, event attributes are received dynamically during event processing, meaning session->evlist is not populated prior to perf_session__process_events(). To handle pipe input correctly: - Register the missing .attr, .tracing_data, .build_id, and .feature callbacks in cmd_sched() - Promote the handlers array to file-scope (latency_handlers[]) and dynamically assign matching tracepoint handlers (or process_sched_ignore) inside perf_sched__process_tracepoint_sample() when evsel->handler is NULL; replace process_sched_wakeup_ignore() with process_sched_ignore() - Perform the trace check post-processing when handling pipe data Fixes: 27295592c22e ("perf session: Share the common trace sample_check routine as perf_session__has_traces") Reviewed-by: Ian Rogers Signed-off-by: Aaron Tomlin Signed-off-by: Namhyung Kim --- tools/perf/builtin-sched.c | 72 +++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 39a375ef209a..7d4c6d6f308e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1581,12 +1581,6 @@ static int process_sched_wakeup_event(const struct perf_tool *tool, return 0; } -static int process_sched_wakeup_ignore(const struct perf_tool *tool __maybe_unused, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) -{ - return 0; -} static bool thread__has_color(struct thread *thread) { @@ -1938,6 +1932,22 @@ typedef int (*tracepoint_handler)(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine); +static struct evsel_str_handler latency_handlers[] = { + { "sched:sched_switch", process_sched_switch_event, }, + { "sched:sched_stat_runtime", process_sched_runtime_event, }, + { "sched:sched_wakeup", process_sched_wakeup_event, }, + { "sched:sched_waking", process_sched_wakeup_event, }, + { "sched:sched_wakeup_new", process_sched_wakeup_event, }, + { "sched:sched_migrate_task", process_sched_migrate_task_event, }, +}; + +static int process_sched_ignore(const struct perf_tool *tool __maybe_unused, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) +{ + return 0; +} + static int perf_sched__process_tracepoint_sample(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample, @@ -1946,7 +1956,23 @@ static int perf_sched__process_tracepoint_sample(const struct perf_tool *tool __ struct evsel *evsel = sample->evsel; int err = 0; - if (evsel->handler != NULL) { + if (evsel->handler == NULL) { + evsel->handler = process_sched_ignore; + for (size_t i = 0; i < ARRAY_SIZE(latency_handlers); i++) { + if (!evsel__name_is(evsel, latency_handlers[i].name)) + continue; + + if (!strcmp(latency_handlers[i].name, "sched:sched_wakeup") && + sample->evsel->evlist && + evlist__find_tracepoint_by_name(sample->evsel->evlist, "sched:sched_waking")) + break; + + evsel->handler = latency_handlers[i].handler; + break; + } + } + + if (evsel->handler != process_sched_ignore) { tracepoint_handler f = evsel->handler; err = f(tool, sample, machine); } @@ -1987,14 +2013,6 @@ static int perf_sched__process_comm(const struct perf_tool *tool __maybe_unused, static int perf_sched__read_events(struct perf_sched *sched) { - struct evsel_str_handler handlers[] = { - { "sched:sched_switch", process_sched_switch_event, }, - { "sched:sched_stat_runtime", process_sched_runtime_event, }, - { "sched:sched_wakeup", process_sched_wakeup_event, }, - { "sched:sched_waking", process_sched_wakeup_event, }, - { "sched:sched_wakeup_new", process_sched_wakeup_event, }, - { "sched:sched_migrate_task", process_sched_migrate_task_event, }, - }; struct perf_session *session; struct perf_data data = { .path = input_name, @@ -2011,14 +2029,17 @@ static int perf_sched__read_events(struct perf_sched *sched) symbol__init(perf_session__env(session)); - /* prefer sched_waking if it is captured */ - if (evlist__find_tracepoint_by_name(session->evlist, "sched:sched_waking")) - handlers[2].handler = process_sched_wakeup_ignore; + if (!perf_data__is_pipe(session->data)) { + /* prefer sched_waking if it is captured */ + if (evlist__find_tracepoint_by_name(session->evlist, "sched:sched_waking")) + latency_handlers[2].handler = process_sched_ignore; - if (perf_session__set_tracepoints_handlers(session, handlers)) - goto out_delete; + if (perf_session__set_tracepoints_handlers(session, latency_handlers)) + goto out_delete; + } - if (!perf_session__has_traces(session, "record -R")) + if (!perf_data__is_pipe(session->data) && + !perf_session__has_traces(session, "record -R")) goto out_delete; err = perf_session__process_events(session); @@ -2027,6 +2048,11 @@ static int perf_sched__read_events(struct perf_sched *sched) goto out_delete; } + if (perf_data__is_pipe(session->data) && + !perf_session__has_traces(session, "record -R")) { + goto out_delete; + } + sched->nr_events = evlist__stats(session->evlist)->nr_events[0]; sched->nr_lost_events = evlist__stats(session->evlist)->total_lost; sched->nr_lost_chunks = evlist__stats(session->evlist)->nr_events[PERF_RECORD_LOST]; @@ -5176,6 +5202,10 @@ int cmd_sched(int argc, const char **argv) sched.tool.namespaces = perf_event__process_namespaces; sched.tool.lost = perf_event__process_lost; sched.tool.fork = perf_sched__process_fork_event; + sched.tool.attr = perf_event__process_attr; + sched.tool.tracing_data = perf_event__process_tracing_data; + sched.tool.build_id = perf_event__process_build_id; + sched.tool.feature = perf_event__process_feature; argc = parse_options_subcommand(argc, argv, sched_options, sched_subcommands, sched_usage, PARSE_OPT_STOP_AT_NON_OPTION);