[PATCH] kunit: tool: Terminate kernel under test on SIGINT

David Gow posted 1 patch 1 month, 2 weeks ago
tools/testing/kunit/kunit_kernel.py | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
[PATCH] kunit: tool: Terminate kernel under test on SIGINT
Posted by David Gow 1 month, 2 weeks ago
kunit.py will attempt to catch SIGINT / ^C in order to ensure the TTY isn't
messed up, but never actually attempts to terminate the running kernel (be
it UML or QEMU). This can lead to a bit of frustration if the kernel has
crashed or hung.

Terminate the kernel process in the signal handler, if it's running. This
requires plumbing through the process handle in a few more places (and
having some checks to see if the kernel is still running in places where it
may have already been killed).

Reported-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Closes: https://lore.kernel.org/all/aaFmiAmg9S18EANA@smile.fi.intel.com/
Signed-off-by: David Gow <david@davidgow.net>
---

This was long overdue, and is much nicer to work with now.

Note that it's likely to conflict with some of the other changes to the
stty sane stuff, such as:
https://lore.kernel.org/all/20260227123136.91086-1-shuvampandey1@gmail.com/

---
 tools/testing/kunit/kunit_kernel.py | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py
index 6f49b184a6fb..c3ebb0ac1116 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -16,7 +16,7 @@ import shutil
 import signal
 import sys
 import threading
-from typing import Iterator, List, Optional, Tuple
+from typing import Iterator, List, Optional, Tuple, Any
 from types import FrameType
 
 import kunit_config
@@ -265,6 +265,7 @@ class LinuxSourceTree:
 		if kconfig_add:
 			kconfig = kunit_config.parse_from_string('\n'.join(kconfig_add))
 			self._kconfig.merge_in_entries(kconfig)
+		self._process : Optional[subprocess.Popen[Any]] = None
 
 	def arch(self) -> str:
 		return self._arch
@@ -362,36 +363,45 @@ class LinuxSourceTree:
 			args.append('kunit.filter_action=' + filter_action)
 		args.append('kunit.enable=1')
 
-		process = self._ops.start(args, build_dir)
-		assert process.stdout is not None  # tell mypy it's set
+		self._process = self._ops.start(args, build_dir)
+		assert self._process is not None # tell mypy it's set
+		assert self._process.stdout is not None  # tell mypy it's set
 
 		# Enforce the timeout in a background thread.
 		def _wait_proc() -> None:
 			try:
-				process.wait(timeout=timeout)
+				if self._process:
+					self._process.wait(timeout=timeout)
 			except Exception as e:
 				print(e)
-				process.terminate()
-				process.wait()
+				if self._process:
+					self._process.terminate()
+					self._process.wait()
 		waiter = threading.Thread(target=_wait_proc)
 		waiter.start()
 
 		output = open(get_outfile_path(build_dir), 'w')
 		try:
 			# Tee the output to the file and to our caller in real time.
-			for line in process.stdout:
+			for line in self._process.stdout:
 				output.write(line)
 				yield line
 		# This runs even if our caller doesn't consume every line.
 		finally:
 			# Flush any leftover output to the file
-			output.write(process.stdout.read())
+			if self._process:
+				if self._process.stdout:
+					output.write(self._process.stdout.read())
+					self._process.stdout.close()
+				self._process = None
 			output.close()
-			process.stdout.close()
 
 			waiter.join()
 			self._restore_terminal_if_tty()
 
 	def signal_handler(self, unused_sig: int, unused_frame: Optional[FrameType]) -> None:
 		logging.error('Build interruption occurred. Cleaning console.')
+		if self._process:
+				self._process.terminate()
+				self._process.wait()
 		self._restore_terminal_if_tty()
-- 
2.53.0
Re: [PATCH] kunit: tool: Terminate kernel under test on SIGINT
Posted by Andy Shevchenko 1 month, 2 weeks ago
On Sat, Feb 28, 2026 at 06:07:22PM +0800, David Gow wrote:
> kunit.py will attempt to catch SIGINT / ^C in order to ensure the TTY isn't
> messed up, but never actually attempts to terminate the running kernel (be
> it UML or QEMU). This can lead to a bit of frustration if the kernel has
> crashed or hung.
> 
> Terminate the kernel process in the signal handler, if it's running. This
> requires plumbing through the process handle in a few more places (and
> having some checks to see if the kernel is still running in places where it
> may have already been killed).

I killed my branch with those experiments already. But it's really appreciated
to see this going to the right direction.

> Reported-by: Andy Shevchenko <andriy.shevchenko@intel.com>

In any case, god bless `git reflog`, I got it still from there and hence

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Tested-by: Andy Shevchenko <andriy.shevchenko@intel.com>

(Have to applied the other mentioned patch first)

Now

  ^CERROR:root:Build interruption occurred. Cleaning console.
  [11:36:29] [ERROR] Test: <missing>: Could not find any KTAP output. Did any KUnit tests run?
  [11:36:29] ============================================================
  [11:36:29] Testing complete. Ran 0 tests: errors: 1
  [11:36:29] Elapsed time: 33.615s total, 0.001s configuring, 5.122s building, 28.492s running

-- 
With Best Regards,
Andy Shevchenko