Files
scylladb/test/scylla_gdb/conftest.py
Jakub Smolar 189b056605 scylla_gdb: use run_ctx to nahdle Scylla exe and remove pexpect
Previous implementation of Scylla lifecycle brought flakiness to the test.
This change leaves lifecycle management up to PythonTest.run_ctx,
which implements more stability logic for setup/teardown.

Replace pexpect-driven GDB interaction with GDB batch mode:
- Avoids DeprecationWarning: "This process is multi-threaded, use of forkpty()
may lead to deadlocks in the child.", which ultimately caused CI deadlocks.
- Removes timeout-driven flakiness on slow systems - no interactive waits/timeouts.
- Produces cleaner, more direct assertions around command execution and output.
- Trade-off: batch mode adds ~10s per command per test,
but with --dist=worksteal this is ~10% overall runtime increase across the suite.

Closes scylladb/scylladb#28484
2026-02-17 11:36:20 +01:00

76 lines
2.4 KiB
Python

# Copyright 2022-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
"""Conftest for Scylla GDB tests"""
import os
import subprocess
import pytest
from test.pylib.runner import testpy_test_fixture_scope
from test.pylib.suite.python import PythonTest
@pytest.fixture(scope=testpy_test_fixture_scope)
async def scylla_server(testpy_test: PythonTest | None):
"""Return a running Scylla server instance from the active test cluster."""
async with testpy_test.run_ctx(options=testpy_test.suite.options) as cluster:
yield next(iter(cluster.running.values()))
@pytest.fixture(scope="module")
def gdb_cmd(scylla_server, request):
"""
Returns a command-line (argv list) that attaches to the `scylla_server` PID, loads `scylla-gdb.py`
and `gdb_utils.py`. This is meant to be executed by `execute_gdb_command()` in `--batch` mode.
"""
scylla_gdb_py = os.path.join(request.fspath.dirname, "..", "..", "scylla-gdb.py")
script_py = os.path.join(request.fspath.dirname, "gdb_utils.py")
cmd = [
"gdb",
"-q",
"--batch",
"--nx",
"-se",
str(scylla_server.exe),
"-p",
str(scylla_server.cmd.pid),
"-ex",
"set python print-stack full",
"-x",
scylla_gdb_py,
"-x",
script_py,
]
return cmd
def execute_gdb_command(gdb_cmd, scylla_command: str = None, full_command: str = None):
"""Execute a single GDB command attached to the running Scylla process.
Builds on `gdb_cmd` and runs GDB via `subprocess.run()` in `--batch` mode.
`scylla_command` is executed as `scylla <cmd>` through GDB's Python interface.
Args:
gdb_cmd: Base GDB argv list returned by the `gdb_cmd` fixture.
scylla_command: Scylla GDB command name/args (from scylla-gdb.py). Mutually exclusive with `full_command`.
full_command: Raw GDB command string to execute. Mutually exclusive with `scylla_command`.
Returns:
Command stdout as a decoded string.
"""
if full_command:
command = [*gdb_cmd, "-ex", full_command]
else:
command = [
*gdb_cmd,
"-ex",
f"python gdb.execute('scylla {scylla_command}')",
]
result = subprocess.run(
command, capture_output=True, text=True, encoding="utf-8", errors="replace"
)
return result