Skip to content

Commit 2742eb0

Browse files
fix: drain asyncssh redirect cleanup in the local ssh harness
asyncssh stores its redirect cleanup coroutines (Queue.join et al) un-awaited and only runs them inside process.wait_closed(); the server handler never called it, so every ssh test leaked coroutines that pytest's unraisable hook surfaced as RuntimeWarnings during GC -- visible as stray noise in xdist runs. Await wait_closed() in the handler and drop the filterwarnings mark, which never covered the GC-time warning anyway. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 72b0eef commit 2742eb0

1 file changed

Lines changed: 7 additions & 8 deletions

File tree

testing/test_ssh_local.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,9 @@
2020

2121
import execnet
2222

23-
pytestmark = [
24-
pytest.mark.skipif(
25-
shutil.which("ssh") is None, reason="system ssh client required"
26-
),
27-
# asyncssh leaves an un-awaited internal Queue.join coroutine on shutdown,
28-
# surfaced by pytest's unraisable-exception hook during GC; harmless here.
29-
pytest.mark.filterwarnings("ignore:coroutine 'Queue.join' was never awaited"),
30-
]
23+
pytestmark = pytest.mark.skipif(
24+
shutil.which("ssh") is None, reason="system ssh client required"
25+
)
3126

3227
# Committed, intentionally-insecure test keys (see sshkeys/README.md).
3328
SSHKEYS = Path(__file__).parent / "sshkeys"
@@ -58,6 +53,10 @@ async def _handle(self, process: asyncssh.SSHServerProcess) -> None:
5853
)
5954
await process.redirect(stdin=proc.stdin, stdout=proc.stdout, stderr=proc.stderr)
6055
process.exit(await proc.wait())
56+
# Drain asyncssh's redirect cleanup coroutines (Queue.join et al):
57+
# they are stored un-awaited and only run inside wait_closed();
58+
# skipping this leaks them and GC prints RuntimeWarnings.
59+
await process.wait_closed()
6160

6261
async def _serve(self) -> None:
6362
self._server = await asyncssh.listen(

0 commit comments

Comments
 (0)