Re: [PATCH v6 2/4] perf sched: Handle missing trace samples in pipe mode

Aaron Tomlin <[email protected]> Sun, 2 Aug 2026 16:17:59 -0400
Newsgroups org.kernel.vger.linux-perf-users
Message-ID <p6d7han43ahvb2f2qwzxqva3ubf4tcj463oirh6wdowbs4qpfq@vczv7tuuc7vg>
On Sun, Aug 02, 2026 at 12:01:40AM +0000, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> 
> New issues:
> - [High] Using `evsel->handler == NULL` to conditionally initialize handlers inside the sample processing hot path causes repeated O(N) evlist iterations for unhandled events and drops late-arriving tracepoints.
> 
> Pre-existing issues:
> - [High] `symbol__init` accesses the `perf_env` before it is populated by pipe feature events, leading to incorrect host-fallback initialization for cross-platform traces.
> - [High] `perf sched timehist` remains completely broken for pipe mode streams.
> --
> 
> --- Patch [2]: [PATCH v6 2/4] perf sched: Handle missing trace samples in pipe mode ---
> commit bdcbf92a5b81c957ee21cce440488c2da3569c14
> Author: Aaron Tomlin <[email protected]>
> 
> 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
>     invoke evlist__set_tracepoints_handlers() dynamically inside
>     perf_sched__process_tracepoint_sample() when evsel->handler is NULL
>   - Perform the trace check post-processing when handling pipe data
> 
> > diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
> > index 94a323da0799a..0abf9f1f3c2e2 100644
> > --- a/tools/perf/builtin-sched.c
> > +++ b/tools/perf/builtin-sched.c
> [ ... ]
> > @@ -1946,6 +1955,14 @@ static int perf_sched__process_tracepoint_sample(const struct perf_tool *tool __
> >  	struct evsel *evsel = sample->evsel;
> >  	int err = 0;
> >  
> > +	if (evsel->handler == NULL && sample->evsel->evlist) {
> > +		/* prefer sched_waking if it is captured */
> > +		if (evlist__find_tracepoint_by_name(sample->evsel->evlist, "sched:sched_waking"))
> > +			latency_handlers[2].handler = process_sched_wakeup_ignore;
> > +
> > +		evlist__set_tracepoints_handlers(sample->evsel->evlist, latency_handlers);
> > +	}
> > +
> 
> [Severity: High]
> Does this cause an O(N) traversal on every sample for unhandled events?
> 
> If a tracepoint is explicitly recorded but not in latency_handlers (such as
> sched:sched_process_fork), evsel->handler will remain NULL. For every sample
> of these unhandled events, this condition evaluates to true.
> 
> This repeatedly triggers evlist__find_tracepoint_by_name() and a call to
> evlist__set_tracepoints_handlers(), which immediately aborts with -EEXIST.
> 
> Could this drop late-arriving tracepoints and cause a significant performance
> regression on the event processing hot path?
> 
> >  	if (evsel->handler != NULL) {
> >  		tracepoint_handler f = evsel->handler;
> >  		err = f(tool, sample, machine);
> [ ... ]
> > @@ -2011,14 +2020,17 @@ static int perf_sched__read_events(struct perf_sched *sched)
> >  
> >  	symbol__init(perf_session__env(session));
> 

Hi Namhyung, Arnaldo, Ian,

This is a valid identified problem.

Because unhandled tracepoints (e.g. sched:sched_process_fork) are not in
latency_handlers[], evsel->handler remained NULL. This caused every
subsequent sample of an unhandled event to re-trigger the O(N) evlist
search and evlist__set_tracepoints_handlers() call on the sample processing
hot path.

Furthermore, __evlist__set_tracepoints_handlers() aborts immediately with
-EEXIST as soon as it encounters a non-NULL handler (e.g.,
sched:sched_switch), which prevented handlers for late-arriving tracepoints
in pipe mode from being registered and caused their samples to be dropped.

To fix this, I have updated perf_sched__process_tracepoint_sample() to
perform a single-pass, per-evsel lazy handler lookup and assign a dummy
sentinel handler (process_sched_ignore) for unhandled events.

This guarantees that evsel->handler is non-NULL after its first sample,
eliminating the hot-path O(N) traversal, bypassing -EEXIST aborts, and
ensuring late-arriving tracepoints in pipe mode are correctly bound.

> [Severity: High]
> This is a pre-existing issue, but does this early symbol__init() call break
> cross-platform pipe mode?
> 
> In pipe mode, perf_env is populated during event processing. Calling
> symbol__init() here accesses an uninitialized env->arch.
> 
> This causes perf_env__os_release() to fall back to the host's uname(),
> permanently poisoning env->os_release and vmlinux_path__init() with host
> paths.
> 
> > -	/* 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;
> [ ... ]
> 
> I also noticed a related pre-existing issue in perf_sched__timehist()
> where timehist remains broken for pipe mode streams:
> 
> tools/perf/builtin-sched.c:perf_sched__timehist() {
> [ ... ]
> 	/* setup per-evsel handlers */
> 	if (perf_session__set_tracepoints_handlers(session, handlers))
> 		goto out;
> 
> 	/* sched_switch event at a minimum needs to exist */
> 	if (!evlist__find_tracepoint_by_name(session->evlist, "sched:sched_switch")) {
> 		pr_err("No sched_switch events found. Have you run 'perf sched record'?\n");
> 		goto out;
> 	}
> [ ... ]
> }
> 
> [Severity: High]
> This is a pre-existing issue, but does this strict check break the
> perf sched timehist subcommand for pipe streams?
> 
> Since the evlist is unpopulated before processing pipe events,
> evlist__find_tracepoint_by_name() fails immediately, causing the timehist
> command to abort.
> 
> -- 
> Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=2

The above are valid too.

However, I will address all of the above in a separate series.


Kind regards,
-- 
Aaron Tomlin