selftests: net: py: add cmd info for ksft_wait failure

Gal recently complained:

  When [ksft_wait failure] happens, the test fails with a cryptic
  message:
    # Exception| Exception: Did not receive ready message

Let's try to include the stdout/stderr of the command we tried
to start. E.g. for cmd("false", ksft_wait=True):

    # Exception| lib.py.utils.CmdInitFailure: Did not receive ready message
    # Exception| CMD: false
    # Exception|   EXIT: 1

We need to factor out _process_terminate() otherwise the exit
path may try to write to already disconnected self.ksft_term_fd.

Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260223202633.4126087-4-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2026-02-23 12:26:33 -08:00
parent 04abab18e1
commit 6e4dff2002

View File

@@ -9,7 +9,15 @@ 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 + "\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,6 +100,17 @@ 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]