From 11606e7e709ec297b607587c6aa9c23eddc3ed33 Mon Sep 17 00:00:00 2001 From: Himani Anil Deshpande Date: Mon, 4 May 2026 16:06:05 -0400 Subject: [PATCH 1/2] [Test] Fix parsing bug with scontrol output for dumping JOb output * Use shelex quote for all filepath to prevent unexpected behaviour from special characters from scontrol * Check for `/` (absolute path), and contains only printable characters. This catches empty strings, non-printable characters (null bytes, carriage returns), and relative/garbage paths. --- .../tests/common/schedulers_common.py | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/tests/integration-tests/tests/common/schedulers_common.py b/tests/integration-tests/tests/common/schedulers_common.py index 7a59c66a05..f218c818c8 100644 --- a/tests/integration-tests/tests/common/schedulers_common.py +++ b/tests/integration-tests/tests/common/schedulers_common.py @@ -11,6 +11,7 @@ import logging import os import re +import shlex from abc import ABCMeta, abstractmethod from assertpy import assert_that @@ -387,6 +388,11 @@ def _submit_batch_job( # noqa: C901 else: return self._remote_command_executor.run_remote_command(submission_command, raise_on_error=raise_on_error) + @staticmethod + def _is_valid_file_path(path): + """Return True if path looks like a valid absolute file path (not empty, no non-printable chars).""" + return not is_blank(path) and path.startswith("/") and path.isprintable() + def _dump_job_output(self, job_info): params = re.split(r"\s+", job_info) stderr = None @@ -396,27 +402,34 @@ def _dump_job_output(self, job_info): match_stdout = re.match(r"StdOut=(.*)?", param) if match_stderr: stderr = match_stderr.group(1) - logging.info("stderr:" + stderr) + logging.info("stderr:%s", stderr) if match_stdout: stdout = match_stdout.group(1) - logging.info("stdout:" + stdout) + logging.info("stdout:%s", stdout) + + # Validate paths: must be absolute and contain only printable characters. + # scontrol may emit empty or non-printable values for StdErr when --wrap is used, + # which would cause bare `cat` (reading from stdin) to hang indefinitely. + stderr = stderr if self._is_valid_file_path(stderr) else None + stdout = stdout if self._is_valid_file_path(stdout) else None + dump_timeout = 60 - if not is_blank(stderr) or not is_blank(stdout): - if not is_blank(stderr) and stderr == stdout: + if stderr or stdout: + if stderr and stderr == stdout: result = self._remote_command_executor.run_remote_command( - f'echo "stderr/stdout:" && cat {stderr}', timeout=dump_timeout + f'echo "stderr/stdout:" && cat {shlex.quote(stderr)}', timeout=dump_timeout ) logging.error(result.stdout) else: - if not is_blank(stderr): + if stderr: stderr_result = self._remote_command_executor.run_remote_command( - f'echo "stderr" && cat {stderr}', timeout=dump_timeout + f'echo "stderr" && cat {shlex.quote(stderr)}', timeout=dump_timeout ) logging.error(stderr_result.stdout) - if not is_blank(stdout): + if stdout: stdout_result = self._remote_command_executor.run_remote_command( - f'echo "stdout" && cat {stdout}', timeout=dump_timeout + f'echo "stdout" && cat {shlex.quote(stdout)}', timeout=dump_timeout ) logging.error(stdout_result.stdout) else: From 64fb76565d7d7f83ed031f10b5ff75e220ad8f1f Mon Sep 17 00:00:00 2001 From: Himani Anil Deshpande Date: Mon, 4 May 2026 16:23:23 -0400 Subject: [PATCH 2/2] [Test] Fix command timeout by using OS level timeout * OS-level timeout command sends SIGTERM after 60 seconds, regardless of PTY/login shell/Fabric behavior * Fabric's SSH timeout set to 70 seconds as a backup, giving the OS timeout 10 seconds to kill the process before the SSH layer intervenes --- .../tests/common/schedulers_common.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/integration-tests/tests/common/schedulers_common.py b/tests/integration-tests/tests/common/schedulers_common.py index f218c818c8..ecdaa20753 100644 --- a/tests/integration-tests/tests/common/schedulers_common.py +++ b/tests/integration-tests/tests/common/schedulers_common.py @@ -417,21 +417,24 @@ def _dump_job_output(self, job_info): if stderr or stdout: if stderr and stderr == stdout: result = self._remote_command_executor.run_remote_command( - f'echo "stderr/stdout:" && cat {shlex.quote(stderr)}', timeout=dump_timeout + f"timeout {dump_timeout} cat {shlex.quote(stderr)}", + timeout=dump_timeout + 10, ) - logging.error(result.stdout) + logging.error(f"stderr/stdout:\n{result.stdout}") else: if stderr: stderr_result = self._remote_command_executor.run_remote_command( - f'echo "stderr" && cat {shlex.quote(stderr)}', timeout=dump_timeout + f"timeout {dump_timeout} cat {shlex.quote(stderr)}", + timeout=dump_timeout + 10, ) - logging.error(stderr_result.stdout) + logging.error(f"stderr:\n{stderr_result.stdout}") if stdout: stdout_result = self._remote_command_executor.run_remote_command( - f'echo "stdout" && cat {shlex.quote(stdout)}', timeout=dump_timeout + f"timeout {dump_timeout} cat {shlex.quote(stdout)}", + timeout=dump_timeout + 10, ) - logging.error(stdout_result.stdout) + logging.error(f"stdout:\n{stdout_result.stdout}") else: logging.error("Unable to retrieve job output.")