summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-02-25 05:25:32 +0300
committerJakub Kicinski <kuba@kernel.org>2026-02-25 05:25:32 +0300
commit7235555e9af67be72bd5ef3f8a28416b93ce2a64 (patch)
tree62dc8bb5a7b6bd78c2353233ed394cf84e9a024a
parent6c32b07650676ab4c112ff8e9d345b6770ae2be5 (diff)
parent6e4dff20021ad280bc9c8e047239707da7689431 (diff)
downloadlinux-7235555e9af67be72bd5ef3f8a28416b93ce2a64.tar.xz
Merge branch 'selftests-net-py-improve-bkg-error-reporting'
Jakub Kicinski says: ==================== selftests: net: py: improve bkg() error reporting bkg() is a helper for running commands in the background. When init or body of a with() block fails check if the bkg() process already exited and report its status (including stdout/ /stderr). This significantly improves debugability. ==================== Link: https://patch.msgid.link/20260223202633.4126087-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--tools/testing/selftests/net/lib/py/utils.py42
1 files changed, 30 insertions, 12 deletions
diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
index 85884f3e827b..09535346c13d 100644
--- a/tools/testing/selftests/net/lib/py/utils.py
+++ b/tools/testing/selftests/net/lib/py/utils.py
@@ -9,9 +9,17 @@ import subprocess
import time
+class CmdInitFailure(Exception):
+ """ Command failed to start. Only raised by bkg(). """
+ def __init__(self, msg, cmd_obj):
+ super().__init__(msg + "\n" + repr(cmd_obj))
+ self.cmd = cmd_obj
+
+
class CmdExitFailure(Exception):
+ """ Command failed (returned non-zero exit code). """
def __init__(self, msg, cmd_obj):
- super().__init__(msg)
+ super().__init__(msg + "\n" + repr(cmd_obj))
self.cmd = cmd_obj
@@ -76,16 +84,13 @@ class cmd:
msg = fd_read_timeout(rfd, ksft_wait)
os.close(rfd)
if not msg:
- raise Exception("Did not receive ready message")
+ terminate = self.proc.poll() is None
+ self._process_terminate(terminate=terminate, timeout=1)
+ raise CmdInitFailure("Did not receive ready message", self)
if not background:
self.process(terminate=False, fail=fail, timeout=timeout)
- def process(self, terminate=True, fail=None, timeout=5):
- if fail is None:
- fail = not terminate
-
- if self.ksft_term_fd:
- os.write(self.ksft_term_fd, b"1")
+ def _process_terminate(self, terminate, timeout):
if terminate:
self.proc.terminate()
stdout, stderr = self.proc.communicate(timeout)
@@ -95,11 +100,21 @@ class cmd:
self.proc.stderr.close()
self.ret = self.proc.returncode
+ return stdout, stderr
+
+ def process(self, terminate=True, fail=None, timeout=5):
+ if fail is None:
+ fail = not terminate
+
+ if self.ksft_term_fd:
+ os.write(self.ksft_term_fd, b"1")
+
+ stdout, stderr = self._process_terminate(terminate=terminate,
+ timeout=timeout)
if self.proc.returncode != 0 and fail:
if len(stderr) > 0 and stderr[-1] == "\n":
stderr = stderr[:-1]
- raise CmdExitFailure("Command failed: %s\nSTDOUT: %s\nSTDERR: %s" %
- (self.proc.args, stdout, stderr), self)
+ raise CmdExitFailure("Command failed", self)
def __repr__(self):
def str_fmt(name, s):
@@ -159,8 +174,11 @@ class bkg(cmd):
return self
def __exit__(self, ex_type, ex_value, ex_tb):
- # Force termination on exception
- terminate = self.terminate or (self._exit_wait and ex_type is not None)
+ terminate = self.terminate
+ # Force termination on exception, but only if bkg() didn't already exit
+ # since forcing termination silences failures with fail=None
+ if self.proc.poll() is None:
+ terminate = terminate or (self._exit_wait and ex_type is not None)
return self.process(terminate=terminate, fail=self.check_fail)