From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v5 1/3] perf test: Add per-test timeout support
Date: Thu, 22 Oct 2026 21:21:39 +0000 [thread overview]
Message-ID: <sashiko-outbox-182058@kernel.org> (raw)
In-Reply-To: <20261022210753.1851597-2-irogers@google.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] perf test: pipe drained before kill_timed_out_group() kills subprocesses
--
commit 9387c80164e94087cba7cfddba4fff510a8fabe3
Author: Ian Rogers <irogers@google.com>
perf test: Add per-test timeout support
This commit adds per-test timeout support to perf test, defaulting to 120
seconds and configurable via -t/--timeout. Forked test children are placed in
their own process groups so timed-out tests and their subprocesses can be
terminated and reported as timeouts in the test summary and JUnit output.
> diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
> index 880eece0bc123..b870ca0bd8262 100644
> --- a/tools/perf/tests/builtin-test.c
> +++ b/tools/perf/tests/builtin-test.c
[ ... ]
> @@ -815,6 +893,106 @@ static void print_test_failure_snippet(FILE *fp, const char *buf)
> free(line_lens);
> }
>
[ ... ]
> +static void kill_timed_out_group(struct child_test *child)
> +{
> + if (!child->timed_out || child->process.finished || child->process.pid <= 0)
> + return;
> +
> + pr_debug3("Sending SIGKILL to remaining processes of timed out test %d.%d (pgid %d)\n",
> + child->suite_num + 1, child->test_case_num + 1, child->process.pid);
> + kill(-child->process.pid, SIGKILL);
> +}
[ ... ]
> +static int reap_child_test(struct child_test *child)
> +{
> + sigset_t oldset;
> + int ret;
> +
> + block_term_signals(&oldset);
> + kill_timed_out_group(child);
> + ret = finish_command(&child->process);
> + child->process.pid = 0;
> + sigprocmask(SIG_SETMASK, &oldset, NULL);
> + return child->timed_out ? TEST_TIMEOUT : ret;
> +}
> +
> static void finish_test(struct child_test **child_tests, int running_test, int child_test_num,
> int width)
> {
[ ... ]
> @@ -904,11 +1088,15 @@ static void finish_test(struct child_test **child_tests, int running_test, int c
> err_done = false;
> buf[len] = '\0';
> strbuf_addstr_safe(&err_output, buf);
> + } else if (pfds[0].revents & (POLLHUP | POLLERR | POLLNVAL)) {
> + close(err);
> + err = -1;
> + child_test->process.err = -1;
> }
> }
> }
> - if (err_done)
> - err_done = check_if_command_finished(&child_test->process);
> + if (err_done || child_test->timed_out)
> + err_done = test_command_finished(child_test);
> }
> /* Drain any remaining data from the pipe. */
> if (err >= 0) {
[ ... ]
> @@ -925,8 +1113,7 @@ static void finish_test(struct child_test **child_tests, int running_test, int c
> fprintf(debug_file(), PERF_COLOR_DELETE_LINE);
> }
> /* Clean up child process. */
> - ret = finish_command(&child_test->process);
> - child_test->process.pid = 0;
> + ret = reap_child_test(child_test);
[ ... ]
> @@ -1157,14 +1350,13 @@ static int finish_tests_parallel(struct child_test **child_tests, size_t num_tes
> if (!child || child->done)
> continue;
>
> - if (check_if_command_finished(&child->process)) {
> + if (test_command_finished(child)) {
> if (child->process.err >= 0) {
> drain_child_process_err(child);
> close(child->process.err);
> child->process.err = -1;
> }
> - child->result = finish_command(&child->process);
> - child->process.pid = 0;
> + child->result = reap_child_test(child);
> clock_gettime(CLOCK_MONOTONIC, &child->end_time);
> child->done = true;
> }
[Severity: Medium]
In tools/perf/tests/builtin-test.c, when running with verbose >= 1 so child
stdout and stderr are piped through process.err, both finish_test() and
finish_tests_parallel() drain the pipe in an unbounded read loop before
calling reap_child_test() -> kill_timed_out_group():
tools/perf/tests/builtin-test.c:finish_test() {
...
if (err_done || child_test->timed_out)
err_done = test_command_finished(child_test);
}
/* Drain any remaining data from the pipe. */
if (err >= 0) {
char buf[512];
ssize_t len;
while ((len = read(err, buf, sizeof(buf) - 1)) > 0) {
buf[len] = '\0';
strbuf_addstr_safe(&err_output, buf);
}
}
...
ret = reap_child_test(child_test);
}
And in parallel mode:
tools/perf/tests/builtin-test.c:finish_tests_parallel() {
...
if (test_command_finished(child)) {
if (child->process.err >= 0) {
drain_child_process_err(child);
close(child->process.err);
child->process.err = -1;
}
child->result = reap_child_test(child);
...
}
If a timed-out test's main child process exits after the initial termination
signal while a subprocess in its process group survives and continuously
writes to stdout or stderr, test_command_finished() returns true once the
main child becomes a zombie. However, kill_timed_out_group() has not yet been
called to terminate the remaining process group members.
Could a noisy surviving subprocess keep feeding the pipe so that the read()
loop in finish_test() or drain_child_process_err() never sees -EAGAIN or
end-of-file, hanging the test runner and growing err_output without bound
before reap_child_test() can call kill_timed_out_group()? Should
kill_timed_out_group() be invoked before draining the pipe when a timed-out
child has finished?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261022210753.1851597-1-irogers@google.com?part=1
next prev parent reply other threads:[~2026-10-22 21:21 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 21:01 [PATCH v1 1/2] perf test: Add per-test timeout support Ian Rogers
2026-09-28 21:01 ` [PATCH v1 2/2] perf test: Improve JUnit XML schema compliance and completeness Ian Rogers
2026-09-28 21:08 ` sashiko-bot
2026-09-28 21:14 ` [PATCH v1 1/2] perf test: Add per-test timeout support sashiko-bot
2026-09-29 1:18 ` [PATCH v2 " Ian Rogers
2026-09-29 1:18 ` [PATCH v2 2/2] perf test: Improve JUnit XML schema compliance and completeness Ian Rogers
2026-09-29 1:24 ` sashiko-bot
2026-09-29 1:31 ` [PATCH v2 1/2] perf test: Add per-test timeout support sashiko-bot
2026-09-29 2:53 ` [PATCH v3 " Ian Rogers
2026-09-29 2:53 ` [PATCH v3 2/2] perf test: Improve JUnit XML schema compliance and completeness Ian Rogers
2026-09-29 2:59 ` sashiko-bot
2026-09-29 3:00 ` [PATCH v3 1/2] perf test: Add per-test timeout support sashiko-bot
2026-10-05 22:44 ` Namhyung Kim
2026-10-12 21:57 ` Ian Rogers
2026-10-12 23:47 ` [PATCH v4 0/3] perf test: Per-test timeouts, JUnit XML compliance, and snippet improvements Ian Rogers
2026-10-12 23:47 ` [PATCH v4 1/3] perf test: Add per-test timeout support Ian Rogers
2026-10-12 23:56 ` sashiko-bot
2026-10-12 23:47 ` [PATCH v4 2/3] perf test: Improve JUnit XML schema compliance and completeness Ian Rogers
2026-10-12 23:54 ` sashiko-bot
2026-10-12 23:47 ` [PATCH v4 3/3] perf test: Avoid stack trace noise in verbose=1 failure snippets Ian Rogers
2026-10-12 23:53 ` sashiko-bot
2026-10-14 21:33 ` [PATCH v4 0/3] perf test: Per-test timeouts, JUnit XML compliance, and snippet improvements Namhyung Kim
2026-10-19 12:22 ` Arnaldo Carvalho de Melo
2026-10-22 16:00 ` Ian Rogers
2026-10-22 21:07 ` [PATCH v5 0/3] perf test: Per-test timeouts and JUnit XML schema compliance Ian Rogers
2026-10-22 21:07 ` [PATCH v5 1/3] perf test: Add per-test timeout support Ian Rogers
2026-10-22 21:21 ` sashiko-bot [this message]
2026-10-22 21:07 ` [PATCH v5 2/3] perf test: Improve JUnit XML schema compliance and completeness Ian Rogers
2026-10-22 21:12 ` sashiko-bot
2026-10-22 21:07 ` [PATCH v5 3/3] perf test: Don't count mlock budget wait time towards test timeout Ian Rogers
2026-10-22 21:12 ` sashiko-bot
2026-10-22 22:22 ` [PATCH v6 0/3] perf test: Per-test timeouts and JUnit XML schema compliance Ian Rogers
2026-10-22 22:22 ` [PATCH v6 1/3] perf test: Add per-test timeout support Ian Rogers
2026-10-22 22:34 ` sashiko-bot
2026-10-22 22:22 ` [PATCH v6 2/3] perf test: Improve JUnit XML schema compliance and completeness Ian Rogers
2026-10-22 22:28 ` sashiko-bot
2026-10-22 22:22 ` [PATCH v6 3/3] perf test: Don't count mlock budget wait time towards test timeout Ian Rogers
2026-10-22 22:27 ` 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-182058@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.