public inbox for linux-perf-users@vger.kernel.org
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: Malcom Gilbert <malcomgilbert@gmail.com>
Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] perf: add timerfd timeout exit-code handling
Date: Sun, 26 Apr 2026 22:48:09 -0700	[thread overview]
Message-ID: <ae74mZg8HDYGJThA@google.com> (raw)
In-Reply-To: <CAJ_TQUzM+JXDy4xo4TgeWBL7f6QA0muLxQ8kEv_0hRw6NqrmZQ@mail.gmail.com>

Hello,

On Sun, Apr 26, 2026 at 01:28:18PM -0500, Malcom Gilbert wrote:
> Assisted-by: OpenAI:gpt-5.3-codex-spark
> Signed-off-by: Malcom Gilbert <malcomgilbert@gmail.com>

Looks like this patch or your system has a problem with indentation.
Please fix.

Thanks,
Namhyung

> ---
>  tools/perf/Documentation/perf-record.txt |  4 +
>  tools/perf/builtin-record.c              | 94 ++++++++++++++++++++++++
>  tools/perf/util/record.h                 |  1 +
>  3 files changed, 99 insertions(+)
> 
> diff --git a/tools/perf/Documentation/perf-record.txt
> b/tools/perf/Documentation/perf-record.txt
> index 178f483140ed..ea48f96fe11a 100644
> --- a/tools/perf/Documentation/perf-record.txt
> +++ b/tools/perf/Documentation/perf-record.txt
> @@ -554,6 +554,10 @@ When processing pre-existing threads
> /proc/XXX/mmap, it may take a long time,
>  because the file may be huge. A time out is needed in such cases.
>  This option sets the time out limit. The default value is 500 ms.
> 
> +--timeout=<seconds>::
> +Stop recording after the given number of seconds.
> +If `perf record` stops from timeout, it exits with status 124.
> +
>  --switch-events::
>  Record context switch events i.e. events of type PERF_RECORD_SWITCH or
>  PERF_RECORD_SWITCH_CPU_WIDE. In some cases (e.g. Intel PT, CoreSight
> or Arm SPE)
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 4a5eba498c02..e666d1d475a4 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -71,6 +71,9 @@
>  #ifdef HAVE_EVENTFD_SUPPORT
>  #include <sys/eventfd.h>
>  #endif
> +#ifdef HAVE_TIMERFD_SUPPORT
> +#include <sys/timerfd.h>
> +#endif
>  #include <sys/mman.h>
>  #include <sys/wait.h>
>  #include <sys/types.h>
> @@ -154,6 +157,9 @@ struct pollfd_index_map {
>  struct record {
>   struct perf_tool tool;
>   struct record_opts opts;
> + int timeout_fd;
> + int timeout_pos;
> + bool timed_out;
>   u64 bytes_written;
>   u64 thread_bytes_written;
>   struct perf_data data;
> @@ -721,6 +727,77 @@ static void sigsegv_handler(int sig)
>   sighandler_dump_stack(sig);
>  }
> 
> +static int record__setup_timeout(struct record *rec)
> +{
> +#ifndef HAVE_TIMERFD_SUPPORT
> + pr_err("perf record --timeout is not supported on this platform\n");
> + return -1;
> +#else
> + struct itimerspec new_value = {};
> + int fd;
> + int pos;
> +
> + if (!rec->opts.timeout)
> + return 0;
> +
> + fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
> + if (fd < 0) {
> + pr_err("Failed to create timeout timerfd, error: %m\n");
> + return -1;
> + }
> +
> + new_value.it_value.tv_sec = rec->opts.timeout;
> +
> + if (timerfd_settime(fd, 0, &new_value, NULL) != 0) {
> + pr_err("Failed to start timeout timer, error: %m\n");
> + close(fd);
> + return -1;
> + }
> +
> + /* Recv all timer expirations in one-shot mode. */
> + pos = fdarray__add(&thread->pollfd, fd, POLLIN, fdarray_flag__nonfilterable);
> + if (pos < 0) {
> + pr_err("Failed to add timeout timerfd to poll list\n");
> + close(fd);
> + return pos;
> + }
> +
> + rec->timeout_fd = fd;
> + rec->timeout_pos = pos;
> +
> + return 0;
> +#endif
> +}
> +
> +static int record__process_timeout_event(struct record *rec)
> +{
> + uint64_t expirations;
> + int pos = rec->timeout_pos;
> + struct pollfd *timeout_pollfd;
> +
> + if (!thread || !thread->pollfd.entries || pos < 0)
> + return 0;
> + if (pos >= thread->pollfd.nr)
> + return 0;
> +
> + timeout_pollfd = &thread->pollfd.entries[pos];
> + if (!(timeout_pollfd->revents & POLLIN))
> + return 0;
> +
> + if (read(rec->timeout_fd, &expirations, sizeof(expirations)) < 0) {
> + if (errno == EAGAIN)
> + return 0;
> + pr_err("failed to read timeout timerfd, error: %m\n");
> + return -1;
> + }
> + (void)expirations;
> +
> + rec->timed_out = true;
> + done = 1;
> +
> + return 0;
> +}
> +
>  static void record__sig_exit(void)
>  {
>   if (signr == -1)
> @@ -2438,6 +2515,9 @@ static int __cmd_record(struct record *rec, int
> argc, const char **argv)
>   float ratio = 0;
>   enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED;
>   struct perf_env *env;
> + rec->timeout_fd = -1;
> + rec->timeout_pos = -1;
> + rec->timed_out = false;
> 
>   atexit(record__sig_exit);
>   signal(SIGCHLD, sig_handler);
> @@ -2647,6 +2727,10 @@ static int __cmd_record(struct record *rec, int
> argc, const char **argv)
>   if (rec->off_cpu)
>   evlist__enable_evsel(rec->evlist, (char *)OFFCPU_EVENT);
> 
> + err = record__setup_timeout(rec);
> + if (err)
> + goto out_child;
> +
>   /*
>   * Let the child rip
>   */
> @@ -2814,6 +2898,10 @@ static int __cmd_record(struct record *rec, int
> argc, const char **argv)
>   err = record__update_evlist_pollfd_from_thread(rec, rec->evlist, thread);
>   if (err)
>   goto out_child;
> +
> + err = record__process_timeout_event(rec);
> + if (err)
> + goto out_child;
>   }
> 
>   if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) {
> @@ -2919,6 +3007,10 @@ static int __cmd_record(struct record *rec, int
> argc, const char **argv)
> 
>   if (rec->off_cpu)
>   rec->bytes_written += off_cpu_write(rec->session);
> + if (rec->timed_out) {
> + signr = -1;
> + status = 124;
> + }
> 
>   record__read_lost_samples(rec);
>   /* this will be recalculated during process_buildids() */
> @@ -3639,6 +3731,8 @@ static struct option __record_options[] = {
>       "\t\t\t  Optionally send control command completion ('ack\\n')
> to ack-fd descriptor.\n"
>       "\t\t\t  Alternatively, ctl-fifo / ack-fifo will be opened and
> used as ctl-fd / ack-fd.",
>        parse_control_option),
> + OPT_UINTEGER(0, "timeout", &record.opts.timeout,
> +     "Stop recording after the given number of seconds"),
>   OPT_CALLBACK(0, "synth", &record.opts, "no|all|task|mmap|cgroup",
>       "Fine-tune event synthesis: default=all", parse_record_synth_option),
>   OPT_STRING_OPTARG_SET(0, "debuginfod", &record.debuginfod.urls,
> diff --git a/tools/perf/util/record.h b/tools/perf/util/record.h
> index 93627c9a7338..576513ed3b60 100644
> --- a/tools/perf/util/record.h
> +++ b/tools/perf/util/record.h
> @@ -80,6 +80,7 @@ struct record_opts {
>   int      ctl_fd_ack;
>   bool      ctl_fd_close;
>   int      synth;
> + unsigned int  timeout;
>   int      threads_spec;
>   const char    *threads_user_spec;
>   u64      off_cpu_thresh_ns;
> --
> 2.43.0
> 
> 
> Malcom

  reply	other threads:[~2026-04-27  5:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-26 18:28 [PATCH] perf: add timerfd timeout exit-code handling Malcom Gilbert
2026-04-27  5:48 ` Namhyung Kim [this message]
     [not found] <CAJ_TQUz0kNV-pUzrcNM7ou3xjPdOU73z+qBAWmP7GUW2BRvpHA@mail.gmail.com>
2026-04-26 18:58 ` Ian Rogers

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=ae74mZg8HDYGJThA@google.com \
    --to=namhyung@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=malcomgilbert@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox