From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v6 1/2] perf timechart: Add a --live mode to the TUI
Date: Fri, 13 Nov 2026 00:00:37 +0000 [thread overview]
Message-ID: <sashiko-outbox-211971@kernel.org> (raw)
In-Reply-To: <20261112233738.699031-2-irogers@google.com>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] perf timechart: unescaped quotes in syscall filter in
LiveRecorder.start()
- [Low] perf timechart: unstarted control_thread.join() in
LiveRecorder._stop()
--
commit 5178221692a3b293f71ade63d89dfc1258413569
Author: Alice Rogers <alice.mei.rogers@gmail.com>
perf timechart: Add a --live mode to the TUI
This commit adds a --live option to perf timechart and ttimechart.py that
runs perf record to stream scheduler, power, or I/O syscall events over a
pipe and displays a rolling window of recent activity in the TUI.
> diff --git a/tools/perf/python/ttimechart.py b/tools/perf/python/ttimechart.py
> index d7ba0276a9fb4..c71afedb453ed 100755
> --- a/tools/perf/python/ttimechart.py
> +++ b/tools/perf/python/ttimechart.py
[ ... ]
> @@ -1726,52 +2210,630 @@ class TimechartApp(App):
> self.goto_task(waker, wake_time)
>
>
> +class PerfPipeTracker:
[ ... ]
> +class LiveRecorder:
[ ... ]
> + def start(self) -> None:
> + """Start perf record, the data is then read from data_fd."""
> + output = open(self.output, "wb") if self.output else None
> + # perf record's ends of the control pipes, closed once it is started.
> + child_fds: List[int] = []
> + try:
> + ctl_r, self.ctl_fd = os.pipe()
> + child_fds.append(ctl_r)
> + self.ack_fd, ack_w = os.pipe()
> + child_fds.append(ack_w)
> + self.wake_r, self.wake_w = os.pipe()
> + os.set_blocking(self.wake_r, False)
> + os.set_blocking(self.wake_w, False)
> + ev_names = self.events()
> + if any(name.startswith("syscalls:") for name in ev_names):
> + own_comm = self.set_own_comm()
> + # common_pid is a thread ID; matching comm excludes all threads
> + # of this process, and $$ excludes the perf record process that
> + # replaces sh via exec.
> + filt = (f'comm != "{own_comm}" && common_pid != $$' if own_comm else
> + f"common_pid != {os.getpid()} && common_pid != $$")
> + ev_args = " ".join(
> + f'-e {shlex.quote(name)} --filter "{filt}"'
> + if name.startswith("syscalls:") else f"-e {shlex.quote(name)}"
> + for name in ev_names
> + )
> + script = ('perf_exe=$1; ctl=$2; shift 2; '
> + 'exec "$perf_exe" record -q -o - -R -c 1 -k mono '
> + f'--synth=task --control "$ctl" {ev_args} -a "$@"')
> + cmd = ["/bin/sh", "-c", script, "sh", self.perf_exe, f"fd:{ctl_r},{ack_w}"]
[Severity: Medium]
Does /bin/sh strip the inner double quotes around own_comm when expanding
--filter "{filt}"?
When set_own_comm() succeeds, interpolating filt into --filter "{filt}"
produces --filter "comm != "ttimechart:..." && common_pid != $$", so the
shell removes the quotes around the comm string before execing perf
record. The kernel tracepoint filter parser requires string operands for
comm to be quoted and rejects the filter with -EINVAL, causing perf
timechart --live -I to fail on startup.
> + if self.workload:
> + cmd += ["--", *self.workload]
> + else:
> + # Quiet so that only errors are written to stderr, see error_text().
> + cmd = [self.perf_exe, "record", "-q", "-o", "-", "-R", "-c", "1", "-k", "mono",
> + "--synth=task", "--control", f"fd:{ctl_r},{ack_w}"]
> + for name in ev_names:
> + cmd += ["-e", name]
> + # Record system wide, as timechart__record() does. Switches into a
> + # task and idle states aren't seen by events following tasks. With
> + # a workload, recording stops when it exits, otherwise when stopped.
> + cmd.append("-a")
> + if self.workload:
> + cmd += ["--", *self.workload]
> + self.origin = monotonic_ns()
> + # A new session so that signals for the terminal aren't received.
> + self.proc = subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
> + stderr=self.stderr, pass_fds=(ctl_r, ack_w),
> + start_new_session=True)
> + assert self.proc.stdout
> + proc_fd = self.proc.stdout.fileno()
> + self.grow_pipe(proc_fd)
> + self.tee_r, tee_w = os.pipe()
> + self.pump_thread = threading.Thread(target=self.pump,
> + args=(proc_fd, tee_w, output),
> + daemon=True)
> + try:
> + self.pump_thread.start()
> + except BaseException:
> + self.pump_thread = None
> + os.close(tee_w)
> + raise
> + # Closed by the pump thread.
> + output = None
> + self.data_fd = self.tee_r
> + self.grow_pipe(self.data_fd)
> + self.control_thread = threading.Thread(target=self.control_loop, daemon=True)
> + self.control_thread.start()
> + except BaseException:
> + self.stop()
[ ... ]
> + def _stop(self) -> None:
> + """Stop perf record and the threads, stop_lock must be held."""
> + proc = self.proc
> + if proc is not None and proc.poll() is None:
> + try:
> + proc.send_signal(signal.SIGINT)
> + proc.wait(timeout=2)
> + except subprocess.TimeoutExpired:
> + # Kill the whole session so a workload isn't left running.
> + try:
> + os.killpg(proc.pid, signal.SIGKILL)
> + except OSError:
> + pass
> + proc.kill()
> + proc.wait()
> + if self.pump_thread and self.pump_thread is not threading.current_thread():
> + self.pump_thread.join(timeout=1)
> + if self.control_thread and self.control_thread is not threading.current_thread():
> + self.control_thread.join(timeout=1)
> + self.close_control_fds()
> + self.close_wake_fds()
> + self.close_data_fds()
> + self.restore_own_comm()
[Severity: Low]
If self.control_thread.start() fails in LiveRecorder.start(), can
self.control_thread.join() here raise RuntimeError and skip the cleanup
that follows?
Unlike self.pump_thread, self.control_thread is not reset to None if
starting the thread raises an exception, so self.stop() -> self._stop()
attempts to join an unstarted thread and aborts before closing the pipe
file descriptors and restoring /proc/self/comm.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112233738.699031-1-irogers@google.com?part=1
next prev parent reply other threads:[~2026-11-13 0:00 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-02 18:26 [PATCH v1 00/13] perf timechart/list/treport: Interactive Textual TUIs and perf python session improvements Ian Rogers
2026-10-02 18:26 ` [PATCH v1 01/13] perf session: Don't flush remaining events once processing is done Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 02/13] perf python: Quietly stop processing events when a callback raises Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 03/13] perf python: Lazily copy events and samples from process_events Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 04/13] perf python: Lazily resolve sample callchains Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 05/13] perf python: Release the GIL while processing session events Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 06/13] perf list: Add a --tui option to launch ilist Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 07/13] perf test: Add a test for the ilist script Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 08/13] perf treport: Show the profile while it loads Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-03 9:31 ` Arnaldo Carvalho de Melo
2026-10-02 18:26 ` [PATCH v1 09/13] perf test: Add a test for the treport script Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-03 9:35 ` Arnaldo Carvalho de Melo
2026-10-02 18:26 ` [PATCH v1 10/13] perf timechart: Add an interactive --tui mode Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 11/13] perf test: Add a test for perf timechart --tui Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 12/13] perf timechart: Add a --live mode to the TUI Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-02 18:26 ` [PATCH v1 13/13] perf test: Test perf timechart --live Ian Rogers
2026-10-03 1:33 ` sashiko-bot
2026-10-03 9:10 ` [PATCH v1 00/13] perf timechart/list/treport: Interactive Textual TUIs and perf python session improvements Arnaldo Carvalho de Melo
2026-10-03 9:12 ` Arnaldo Carvalho de Melo
2026-10-03 9:15 ` Arnaldo Carvalho de Melo
2026-10-14 4:22 ` [PATCH v2 0/2] perf timechart: Add --live mode to the TUI and test Ian Rogers
2026-10-14 4:22 ` [PATCH v2 1/2] perf timechart: Add a --live mode to the TUI Ian Rogers
2026-10-14 4:35 ` sashiko-bot
2026-10-14 4:22 ` [PATCH v2 2/2] perf test: Test perf timechart --live Ian Rogers
2026-10-14 4:28 ` sashiko-bot
2026-10-23 4:18 ` [PATCH v3 0/2] perf timechart: Add --live mode to the TUI and test Ian Rogers
2026-10-23 4:18 ` [PATCH v3 1/2] perf timechart: Add a --live mode to the TUI Ian Rogers
2026-10-23 4:37 ` sashiko-bot
2026-10-23 4:18 ` [PATCH v3 2/2] perf test: Test perf timechart --live Ian Rogers
2026-10-23 4:23 ` sashiko-bot
2026-10-23 5:02 ` [PATCH v4 0/2] perf timechart: Add --live mode to the TUI and test Ian Rogers
2026-10-23 5:02 ` [PATCH v4 1/2] perf timechart: Add a --live mode to the TUI Ian Rogers
2026-10-23 5:25 ` sashiko-bot
2026-10-23 5:02 ` [PATCH v4 2/2] perf test: Test perf timechart --live Ian Rogers
2026-10-23 5:07 ` sashiko-bot
2026-10-23 5:49 ` [PATCH v5 0/2] perf timechart: Add --live mode to the TUI and test Ian Rogers
2026-10-23 5:49 ` [PATCH v5 1/2] perf timechart: Add a --live mode to the TUI Ian Rogers
2026-10-23 6:16 ` sashiko-bot
2026-10-23 5:49 ` [PATCH v5 2/2] perf test: Test perf timechart --live Ian Rogers
2026-10-23 6:01 ` sashiko-bot
2026-11-12 23:37 ` [PATCH v6 0/2] perf timechart: Add --live mode to the TUI and test Ian Rogers
2026-11-12 23:37 ` [PATCH v6 1/2] perf timechart: Add a --live mode to the TUI Ian Rogers
2026-11-13 0:00 ` sashiko-bot [this message]
2026-11-12 23:37 ` [PATCH v6 2/2] perf test: Test perf timechart --live Ian Rogers
2026-11-12 23:43 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-211971@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=irogers@google.com \
--cc=linux-perf-users@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.