From 4bbdaff5ef465023ca9b1e8113360904afd27ece Mon Sep 17 00:00:00 2001 From: Cyd Date: Sat, 18 Jul 2026 00:23:48 -0500 Subject: [PATCH] Mash tool: Ctrl+C ends the run early with a full summary Stopping early is a real operator workflow (finger fatigue); previously an interrupt died summary-less and could orphan a process holding the COM port. CancelKeyPress now breaks the run loop, snapshots the after- counters, and prints the summary with the actual elapsed duration. Co-Authored-By: Claude Fable 5 --- tools/RioSerialMonitor/MashTest.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/RioSerialMonitor/MashTest.cs b/tools/RioSerialMonitor/MashTest.cs index 7c66baa..27e7eda 100644 --- a/tools/RioSerialMonitor/MashTest.cs +++ b/tools/RioSerialMonitor/MashTest.cs @@ -224,6 +224,16 @@ internal static class MashTest using var cts = new CancellationTokenSource(); Task run = link.RunAsync(cts.Token); + // Ctrl+C = "my fingers hurt": end the run NOW but still snapshot the + // counters and print the full summary, instead of dying summary-less + // (and leaving an orphan holding the port, as an interrupted run did). + bool stopRequested = false; + Console.CancelKeyPress += (_, e) => + { + e.Cancel = true; // we shut down ourselves + stopRequested = true; + }; + // --- counters BEFORE --------------------------------------------------- await Task.Delay(500); Dictionary before = await SnapshotStatusAsync(); @@ -232,6 +242,7 @@ internal static class MashTest Raw(""); Raw(">>> MASH NOW: two hands, 8 lamp buttons, as fast as you can. <<<"); Raw($">>> Test runs {seconds}s. A wedge alarm will beep + banner. <<<"); + Raw(">>> Ctrl+C ends the run early and still prints the summary. <<<"); Raw(""); // --- wedge watchdog + progress ticker ---------------------------------- @@ -239,6 +250,12 @@ internal static class MashTest TimeSpan nextProgress = sw.Elapsed + TimeSpan.FromSeconds(30); while (sw.Elapsed < runEnd) { + if (stopRequested) + { + seconds = (int)sw.Elapsed.TotalSeconds; // summary reflects reality + Log("operator stop (Ctrl+C) — ending run, snapshotting counters..."); + break; + } await Task.Delay(100); lock (gate) {