[PATCH 1/2] rteval: cyclictest: Improve handling of truncated histogram output

John Kacur <[email protected]> Fri, 5 Jun 2026 17:06:47 -0400
Newsgroups org.kernel.vger.linux-rt-users
Message-ID <[email protected]>
When cyclictest is terminated with SIGINT during rteval shutdown, the
output buffer may not be fully flushed, resulting in an incomplete
final histogram line. This caused IndexError warnings when parsing.

Changes:
- Validate histogram lines have expected field count before parsing
  (1 index + numcores values) to skip incomplete lines early
- Downgrade parsing error from WARN to DEBUG since incomplete output
  is expected during normal process termination
- Calculate expected field count dynamically based on actual core count

This eliminates confusing warnings during normal operation while still
catching unexpected parsing issues in debug logs.

Assisted-by: Claude Sonnet 4.5 <[email protected]>
Signed-off-by: John Kacur <[email protected]>
---
 rteval/modules/measurement/cyclictest.py | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/rteval/modules/measurement/cyclictest.py b/rteval/modules/measurement/cyclictest.py
index a120a552da11..a1bf0d2d7324 100644
--- a/rteval/modules/measurement/cyclictest.py
+++ b/rteval/modules/measurement/cyclictest.py
@@ -404,13 +404,21 @@ class Cyclictest(rtevalModulePrototype):
                     self._log(Log.DEBUG, f"cyclictest: unexpected output: {line}")
                     continue
 
+                # Validate line has expected number of fields: 1 index + (cores * 1 value)
+                expected_fields = 1 + self.__numcores
+                if len(vals) < expected_fields:
+                    self._log(Log.DEBUG, f'Skipping incomplete histogram line at bucket {index} '
+                              f'({len(vals)} fields, expected {expected_fields})')
+                    continue
+
                 for i, core in enumerate(self.__cpus):
                     try:
                         self.__cyclicdata[core].bucket(index, int(vals[i+1]))
                         self.__cyclicdata['system'].bucket(index, int(vals[i+1]))
                     except (IndexError, ValueError) as e:
                         # Handle partial output from cyclictest (can happen on SIGINT during cleanup)
-                        self._log(Log.WARN, f"Error parsing cyclictest bucket data for core {core}: {e}")
+                        self._log(Log.DEBUG, f"Skipping incomplete bucket data for core {core} "
+                                  f"(expected during process termination): {e}")
                         continue
 
             # generate statistics for each RunData object
-- 
2.54.0