All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v7] perf record: Fix unhandled POLLHUP on non_perf_event descriptors
Date: Thu, 20 Aug 2026 20:17:43 +0000	[thread overview]
Message-ID: <20260820201743.DB45A1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260820200214.2865570-1-irogers@google.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The patch fails to fix the `-EINVAL` pollfd mismatch abort and introduces dead code because it relies on an invalid assumption about `fdarray__filter()`.
- [Medium] The newly added unit test `test__fdarray__filter` asserts an incorrect invariant about `fdarray__filter()`, causing deterministic test failure.
--

--- Patch [1]: [PATCH v7] perf record: Fix unhandled POLLHUP on non_perf_event descriptors ---
commit c8946dae2d12736f0f97f47367d99aaa40d80c15
Author: Ian Rogers <irogers@google.com>
Subject: perf record: Fix unhandled POLLHUP on non_perf_event descriptors

This commit attempts to fix an abort during perf record teardown caused by
index mismatches between a thread's localized poll array and the core evlist
poll array when handling POLLHUP. It propagates the finalized -1 state from
the core evlist back to the thread's local array before the equivalence check.
It also adds a unit test to verify that fdarray__filter preserves nonfilterable
items.

> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index e915390556752..1ddf3ad2808df 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -1180,6 +1180,21 @@ static int record__update_evlist_pollfd_from_thread(struct record *rec,
>  		int e_pos = rec->index_map[i].evlist_pollfd_index;
>  		int t_pos = rec->index_map[i].thread_pollfd_index;
>  
> +		if (e_entries[e_pos].fd == -1 || e_entries[e_pos].events == 0) {
> +			/*
> +			 * If the control file descriptor was closed, then evlist__ctlfd_process()
> +			 * will have called evlist__finalize_ctlfd() on the PREVIOUS loop iteration
> +			 * to cleanly set the core evlist's e_entries[e_pos].fd to -1.
> +			 *
> +			 * Since nonfilterable items are skipped by fdarray__filter(), the
> +			 * thread's local t_entries[t_pos] retains its original state.
> +			 * We must explicitly propagate the finalized -1 state to t_entries
> +			 * BEFORE evaluating the strict equivalence check below.
> +			 */
> +			t_entries[t_pos].fd = -1;
> +			t_entries[t_pos].events = 0;
> +		}
> +
>  		if (e_entries[e_pos].fd != t_entries[t_pos].fd ||
>  		    e_entries[e_pos].events != t_entries[t_pos].events) {
>  			pr_err("Thread and evlist pollfd index mismatch\n");

[Severity: High]
Does this fix actually resolve the mismatch? A POLLHUP event on the control
descriptor causes fdarray__filter to unconditionally clear t_entries[t_pos].events
to 0.

Since e_entries has not yet been processed by evlist__ctlfd_process, its events
is still POLLIN. This means the e_entries condition evaluates to false, making
the new block dead code.

Consequently, the strict equivalence check below evaluates to true (POLLIN != 0),
causing the function to abort with -EINVAL.

> diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
> index 40983c3574b12..23860edb8ef09 100644
> --- a/tools/perf/tests/fdarray.c
> +++ b/tools/perf/tests/fdarray.c
> @@ -80,6 +80,38 @@ static int test__fdarray__filter(struct test_suite *test __maybe_unused, int sub
>  		goto out_delete;
>  	}
>  
> +	fdarray__init_revents(fda, POLLHUP);
> +	fda->priv[2].flags = fdarray_flag__nonfilterable;
> +
> +	pr_debug("\nfiltering all but fda->entries[2] (nonfilterable):");
> +	fdarray__fprintf_prefix(fda, "before", stderr);
> +
> +	/*
> +	 * Note: fdarray__filter() in tools/lib/api/fd/array.c evaluates the
> +	 * fdarray_flag__nonfilterable flag at the very top of its loop via an
> +	 * early continue. Therefore, it completely skips all processing for this
> +	 * descriptor, guaranteeing its fd, events, and revents fields remain
> +	 * entirely untouched by the filter mask evaluation below it.
> +	 */
> +	nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL);
> +	fdarray__fprintf_prefix(fda, " after", stderr);
> +
> +	if (nr_fds != 0) {
> +		pr_debug("\nfdarray__filter()=%d != 0, should be 0\n",
> +			 nr_fds);
> +		goto out_delete;
> +	}
> +	if (fda->entries[2].fd == -1) {
> +		pr_debug("\nfdarray__filter() illegally modified nonfilterable fd!");
> +		goto out_delete;
> +	}
> +	if (fda->entries[2].revents != POLLHUP) {
> +		pr_debug("\nfdarray__filter() illegally modified nonfilterable revents!");

[Severity: Medium]
Will this test pass? The fdarray__filter function in tools/lib/api/fd/array.c
actively clears events and revents prior to checking the nonfilterable flag:

if (fda->entries[fd].revents & revents) {
	...
	fda->entries[fd].revents = fda->entries[fd].events = 0;
	continue;
}

if (!(fda->priv[fd].flags & fdarray_flag__nonfilterable))

This implementation contradicts the test's assumption that the fields remain
untouched, causing the fda->entries[2].revents != POLLHUP assertion to
deterministically fail.

> +		goto out_delete;
> +	}
> +
> +	fda->priv[2].flags = 0; /* reset flags */
> +
>  	pr_debug("\n");
>  
>  	err = 0;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260820200214.2865570-1-irogers@google.com?part=1

  reply	other threads:[~2026-08-20 20:17 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-10  5:39 [PATCH v1 1/2] perf record: Fix teardown hang on system-wide multi-threaded sessions Ian Rogers
2026-07-10  5:39 ` [PATCH v1 2/2] perf cap: If capability is missing still perform root test Ian Rogers
2026-07-10  5:47   ` sashiko-bot
2026-07-10 22:24     ` Namhyung Kim
2026-07-16  7:40       ` [PATCH v2] perf cap: Remove used_root parameter and simplify capability checks Ian Rogers
2026-07-23  5:06         ` [PATCH v3] " Ian Rogers
2026-07-24  5:47           ` Namhyung Kim
2026-07-10  5:56 ` [PATCH v1 1/2] perf record: Fix teardown hang on system-wide multi-threaded sessions sashiko-bot
2026-07-10 22:02 ` Namhyung Kim
2026-07-12  6:56 ` (subset) " Namhyung Kim
2026-07-16  7:37   ` [PATCH v2] perf record: Fix destructor invocation and event counting in fdarray__filter Ian Rogers
2026-07-16  8:00     ` sashiko-bot
2026-07-23  5:04     ` [PATCH v3] " Ian Rogers
2026-07-23  5:27       ` sashiko-bot
2026-08-17 23:04       ` [PATCH v4] perf fdarray: " Ian Rogers
2026-08-17 23:17         ` Namhyung Kim
2026-08-17 23:30           ` Ian Rogers
2026-08-17 23:28         ` sashiko-bot
2026-08-18  0:31         ` [PATCH v5] perf record: Fix unhandled POLLHUP on non_perf_event descriptors Ian Rogers
2026-08-18  0:43           ` sashiko-bot
2026-08-20 16:49           ` [PATCH v6] " Ian Rogers
2026-08-20 17:00             ` sashiko-bot
2026-08-20 20:02             ` [PATCH v7] " Ian Rogers
2026-08-20 20:17               ` sashiko-bot [this message]
2026-08-20 21:37               ` [PATCH v8] " Ian Rogers
2026-08-20 21:47                 ` sashiko-bot
2026-08-20 22:00                   ` 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=20260820201743.DB45A1F000E9@smtp.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.