From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from relay.smtp-ext.broadcom.com (relay.smtp-ext.broadcom.com [192.19.144.205]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B48413C1097; Fri, 24 Jul 2026 21:41:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.19.144.205 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784929291; cv=none; b=cJbmUXjUvONj8G+Xr9ZTOPmB0Zsh2G0AKA1c480pvHpaFqTTc42l4N4KSn2p/hNjdGvQP4/RoaRsc0VeAvr39SyLPs3Ojk6ZH0jzoOi48qOAz6xjv0WoSpj4qdeuWrOT8MtmBD3h4b+aX+E1TAFE5fwEDDkQVpBTw5ITB2RyOEE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784929291; c=relaxed/simple; bh=6bIR/igc8vtJnwe2y1aD78jUwOu4p7lxaqy0G9VYVCo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Ndx0YT8qfBRUrzPmnTS8jsDYBojGxLQPUr6BX44pL+cNtKB02xOpzgfClkHqF+tsUtNRF2ZHteMF+WNoTnUJl9+BTrFot0AWeEM2HN7LUdwJhhGCtwNAv4fWKSYwcYOmX138Svcx8bea6yOayOErcMca6URMa5sGSTpGmggueM8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=CJYyCdcU; arc=none smtp.client-ip=192.19.144.205 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="CJYyCdcU" Received: from mail-lvn-it-01.broadcom.com (mail-lvn-it-01.lvn.broadcom.net [10.36.132.253]) by relay.smtp-ext.broadcom.com (Postfix) with ESMTP id 551F3C0000F9; Fri, 24 Jul 2026 14:41:23 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 relay.smtp-ext.broadcom.com 551F3C0000F9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com; s=dkimrelay; t=1784929283; bh=6bIR/igc8vtJnwe2y1aD78jUwOu4p7lxaqy0G9VYVCo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CJYyCdcUFWFjlHqsjLXkitcJEJLrYg5So/9dA5K9khMILJItPWq+fSa7EpoblrrC1 Q6RVdH6yrSkXeo8KTkmSgb+yNXfkVpJmcZEG6h5oLZLPzAucn/HaObTiCeWgaf7fHl OYit4J/S9heBFS62V4P24EEYQCSr0lV77OXgeaCo= Received: from stbirv-lnx-1.igp.broadcom.net (stbirv-lnx-1.igp.broadcom.net [10.67.48.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mail-lvn-it-01.broadcom.com (Postfix) with ESMTPSA id D0CF5ACD; Fri, 24 Jul 2026 14:41:22 -0700 (PDT) From: Florian Fainelli To: stable@vger.kernel.org Cc: Shuvam Pandey , David Gow , Shuah Khan , Florian Fainelli , Richard Weinberger , Anton Ivanov , Johannes Berg , Brendan Higgins , Rae Moar , Kees Cook , Jens Axboe , Al Viro , Tiwei Bie , linux-um@lists.infradead.org (open list:USER-MODE LINUX (UML)), linux-kernel@vger.kernel.org (open list), linux-kselftest@vger.kernel.org (open list:KERNEL UNIT TESTING FRAMEWORK (KUnit)), kunit-dev@googlegroups.com (open list:KERNEL UNIT TESTING FRAMEWORK (KUnit)), bcm-kernel-feedback-list@broadcom.com Subject: [PATCH stable 6.12 8/9] kunit: tool: skip stty when stdin is not a tty Date: Fri, 24 Jul 2026 14:41:18 -0700 Message-Id: <20260724214119.1066665-9-florian.fainelli@broadcom.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260724214119.1066665-1-florian.fainelli@broadcom.com> References: <20260724214119.1066665-1-florian.fainelli@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Shuvam Pandey commit e42c349f4cdfa43cb39a68c8f764f8cafc23a9a9 upstream run_kernel() cleanup and signal_handler() invoke stty unconditionally. When stdin is not a tty (for example in CI or unit tests), this writes noise to stderr. Call stty only when stdin is a tty. Add regression tests for these paths: - run_kernel() with non-tty stdin - signal_handler() with non-tty stdin - signal_handler() with tty stdin Signed-off-by: Shuvam Pandey Reviewed-by: David Gow Signed-off-by: Shuah Khan [florian: add missing 'import sys' required by sys.stdin.isatty(); the module was already present in the mainline tree before this commit but was absent from the 6.12 base of kunit_kernel.py] Signed-off-by: Florian Fainelli --- tools/testing/kunit/kunit_kernel.py | 11 +++++-- tools/testing/kunit/kunit_tool_test.py | 42 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py index 3f2979f2f6ea..c09b66ba734b 100644 --- a/tools/testing/kunit/kunit_kernel.py +++ b/tools/testing/kunit/kunit_kernel.py @@ -14,6 +14,7 @@ import os import shlex import shutil import signal +import sys import threading from typing import Iterator, List, Optional, Tuple, Any from types import FrameType @@ -333,6 +334,12 @@ class LinuxSourceTree: return False return self.validate_config(build_dir) + def _restore_terminal_if_tty(self) -> None: + # stty requires a controlling terminal; skip headless runs. + if sys.stdin is None or not sys.stdin.isatty(): + return + subprocess.call(['stty', 'sane']) + def run_kernel(self, args: Optional[List[str]]=None, build_dir: str='', filter_glob: str='', filter: str='', filter_action: Optional[str]=None, timeout: Optional[int]=None) -> Iterator[str]: # Copy to avoid mutating the caller-supplied list. exec_tests() reuses # the same args across repeated run_kernel() calls (e.g. --run_isolated), @@ -380,11 +387,11 @@ class LinuxSourceTree: output.close() waiter.join() - subprocess.call(['stty', 'sane']) + 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() - subprocess.call(['stty', 'sane']) + self._restore_terminal_if_tty() diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py index 70e5d0abe87f..6e6200d52540 100755 --- a/tools/testing/kunit/kunit_tool_test.py +++ b/tools/testing/kunit/kunit_tool_test.py @@ -503,6 +503,48 @@ class LinuxSourceTreeTest(unittest.TestCase): self.assertIn('kunit.filter_glob=suite.test1', start_calls[0]) self.assertIn('kunit.filter_glob=suite.test2', start_calls[1]) + def test_run_kernel_skips_terminal_reset_without_tty(self): + def fake_start(unused_args, unused_build_dir): + return subprocess.Popen(['printf', 'KTAP version 1\n'], + text=True, stdout=subprocess.PIPE) + + non_tty_stdin = mock.Mock() + non_tty_stdin.isatty.return_value = False + + with tempfile.TemporaryDirectory('') as build_dir: + tree = kunit_kernel.LinuxSourceTree(build_dir, kunitconfig_paths=[os.devnull]) + with mock.patch.object(tree._ops, 'start', side_effect=fake_start), \ + mock.patch.object(kunit_kernel.sys, 'stdin', non_tty_stdin), \ + mock.patch.object(kunit_kernel.subprocess, 'call') as mock_call: + for _ in tree.run_kernel(build_dir=build_dir): + pass + + mock_call.assert_not_called() + + def test_signal_handler_skips_terminal_reset_without_tty(self): + non_tty_stdin = mock.Mock() + non_tty_stdin.isatty.return_value = False + tree = kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[os.devnull]) + + with mock.patch.object(kunit_kernel.sys, 'stdin', non_tty_stdin), \ + mock.patch.object(kunit_kernel.subprocess, 'call') as mock_call, \ + mock.patch.object(kunit_kernel.logging, 'error') as mock_error: + tree.signal_handler(signal.SIGINT, None) + mock_error.assert_called_once() + mock_call.assert_not_called() + + def test_signal_handler_resets_terminal_with_tty(self): + tty_stdin = mock.Mock() + tty_stdin.isatty.return_value = True + tree = kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[os.devnull]) + + with mock.patch.object(kunit_kernel.sys, 'stdin', tty_stdin), \ + mock.patch.object(kunit_kernel.subprocess, 'call') as mock_call, \ + mock.patch.object(kunit_kernel.logging, 'error') as mock_error: + tree.signal_handler(signal.SIGINT, None) + mock_error.assert_called_once() + mock_call.assert_called_once_with(['stty', 'sane']) + def test_build_reconfig_no_config(self): with tempfile.TemporaryDirectory('') as build_dir: with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: -- 2.34.1