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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox