mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
perf test: Avoid stack trace noise in verbose=1 failure snippets
When a test fails with a signal or times out, child_test_sig_handler()
appends '---- unexpected signal (<sig>) ----' followed by a multi-line
stack trace (' #0 ...' through '_start').
In verbose=1 mode, print_test_failure_snippet() selects up to
failure_snippet_lines (10) lines:
- Pass 1 selects lines matching failure keywords plus their immediate
next line (' #0 ... in child_test_sig_handler').
- Pass 2 fills the remaining quota by scanning backwards from the end
of the output buffer, which consumes the remaining lines on outermost
stack frames ('handle_internal_command', 'run_argv', 'main',
'__libc_start_main', '_start') and hides the trailing test output
showing where the test had run to.
Improve print_test_failure_snippet() by:
- Skipping blank lines and stack trace lines (' #<digit>...') when
selecting context in Pass 1 and when scanning backwards from the end
in Pass 2, with a Pass 3 fallback from the top of the buffer if quota
still remains.
- Prioritizing the non-blank line immediately preceding
'---- unexpected signal' so there is no '...' gap before the signal
message.
- Only printing '...' between selected lines when at least one non-blank
line was omitted between them.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
dd1c6ac2f7
commit
aa68bfb7b0
|
|
@ -694,6 +694,47 @@ static void print_line_highlighted(FILE *fp, const char *line, size_t len)
|
|||
}
|
||||
|
||||
|
||||
static bool is_blank_line(const char *line, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (!isspace((unsigned char)line[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_stack_line(const char *line, size_t len)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
while (i < len && isspace((unsigned char)line[i]))
|
||||
i++;
|
||||
return i + 1 < len && line[i] == '#' && isdigit((unsigned char)line[i + 1]);
|
||||
}
|
||||
|
||||
static bool is_ignorable_snippet_line(const char *line, size_t len)
|
||||
{
|
||||
return is_blank_line(line, len) || is_stack_line(line, len);
|
||||
}
|
||||
|
||||
static bool has_non_blank_between(const char **lines, const size_t *line_lens,
|
||||
size_t start, size_t end)
|
||||
{
|
||||
for (size_t j = start + 1; j < end; j++) {
|
||||
if (!is_blank_line(lines[j], line_lens[j]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pick_snippet_line(bool *pick, size_t idx, unsigned int *picked_count)
|
||||
{
|
||||
if (!pick[idx] && *picked_count < failure_snippet_lines) {
|
||||
pick[idx] = true;
|
||||
(*picked_count)++;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_test_failure_snippet(FILE *fp, const char *buf)
|
||||
{
|
||||
size_t num_lines = 0;
|
||||
|
|
@ -764,43 +805,63 @@ static void print_test_failure_snippet(FILE *fp, const char *buf)
|
|||
}
|
||||
|
||||
/* Pass 0: Always pick the very first line */
|
||||
if (num_lines > 0 && picked_count < failure_snippet_lines) {
|
||||
pick[0] = true;
|
||||
picked_count++;
|
||||
}
|
||||
if (num_lines > 0)
|
||||
pick_snippet_line(pick, 0, &picked_count);
|
||||
|
||||
/* Pass 1: Pick lines with failure keywords from start (Highest Priority) */
|
||||
for (i = 0; i < num_lines && picked_count < failure_snippet_lines; i++) {
|
||||
size_t dummy;
|
||||
|
||||
if (find_next_keyword(lines[i], line_lens[i], &dummy)) {
|
||||
if (!pick[i]) {
|
||||
pick[i] = true;
|
||||
picked_count++;
|
||||
}
|
||||
/* Prioritize getting the immediate next line for context */
|
||||
if (i + 1 < num_lines && !pick[i + 1] &&
|
||||
picked_count < failure_snippet_lines) {
|
||||
pick[i + 1] = true;
|
||||
picked_count++;
|
||||
if (is_ignorable_snippet_line(lines[i], line_lens[i]))
|
||||
continue;
|
||||
if (!find_next_keyword(lines[i], line_lens[i], &dummy))
|
||||
continue;
|
||||
|
||||
pick_snippet_line(pick, i, &picked_count);
|
||||
/*
|
||||
* For unexpected signals, prioritize the preceding non-blank
|
||||
* line showing where the test had run to before the signal.
|
||||
*/
|
||||
if (!strncmp(lines[i], "---- unexpected signal", 22)) {
|
||||
size_t j = i;
|
||||
|
||||
while (j > 0) {
|
||||
j--;
|
||||
if (!is_ignorable_snippet_line(lines[j], line_lens[j])) {
|
||||
pick_snippet_line(pick, j, &picked_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Prioritize getting the immediate next line for context */
|
||||
if (i + 1 < num_lines &&
|
||||
!is_ignorable_snippet_line(lines[i + 1], line_lens[i + 1]))
|
||||
pick_snippet_line(pick, i + 1, &picked_count);
|
||||
}
|
||||
|
||||
/* Pass 2: Fill remaining quota from the end backwards */
|
||||
/*
|
||||
* Pass 2: Fill remaining quota from the end backwards, skipping blank
|
||||
* and stack trace lines so trailing test progress is shown instead of
|
||||
* outermost stack frames like main/_start.
|
||||
*/
|
||||
i = num_lines;
|
||||
while (i > 0 && picked_count < failure_snippet_lines) {
|
||||
i--;
|
||||
if (!pick[i]) {
|
||||
pick[i] = true;
|
||||
picked_count++;
|
||||
}
|
||||
if (!is_ignorable_snippet_line(lines[i], line_lens[i]))
|
||||
pick_snippet_line(pick, i, &picked_count);
|
||||
}
|
||||
|
||||
/* Pass 3: Fallback to top stack frames if quota remains */
|
||||
for (i = 0; i < num_lines && picked_count < failure_snippet_lines; i++) {
|
||||
if (!is_blank_line(lines[i], line_lens[i]))
|
||||
pick_snippet_line(pick, i, &picked_count);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_lines; i++) {
|
||||
if (!pick[i])
|
||||
continue;
|
||||
if (last_printed != -1 && (int)i > last_printed + 1) {
|
||||
if (last_printed != -1 &&
|
||||
has_non_blank_between(lines, line_lens, last_printed, i)) {
|
||||
if (perf_use_color_default)
|
||||
fprintf(fp, "%s...%s\n", PERF_COLOR_BLUE, PERF_COLOR_RESET);
|
||||
else
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user