All of lore.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 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.