Stop cancelled remote queries without blocking the selector
RemoteQueryPool.cancel() terminated the SSH process and then waited up to 250 ms for it, on the curses thread. Ctrl+R re-enqueues every host, so a refresh of six hosts could freeze the popup for over a second. Only send SIGTERM when cancelling; reap the process on later polls, escalating to SIGKILL after 250 ms and closing its pipes once it has exited. close() still waits, since the popup is exiting anyway. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -282,6 +282,33 @@ class RemoteSshTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(decode_remote_output("错误".encode("gbk")), "错误")
|
||||
|
||||
def test_cancel_does_not_block_and_reaps_the_process_later(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
slow_ssh = Path(directory) / "ssh"
|
||||
# Ignore SIGTERM so the pool has to escalate to SIGKILL.
|
||||
slow_ssh.write_text("#!/bin/sh\ntrap '' TERM\nsleep 5 & wait\n", encoding="utf-8")
|
||||
slow_ssh.chmod(0o755)
|
||||
pool = RemoteQueryPool(str(slow_ssh), query_timeout=5)
|
||||
self.addCleanup(pool.close)
|
||||
pool.enqueue(RemoteEntry("slow"))
|
||||
time.sleep(0.05)
|
||||
process = pool._active["slow"].process # type: ignore[attr-defined]
|
||||
|
||||
started = time.monotonic()
|
||||
pool.cancel("slow")
|
||||
self.assertLess(time.monotonic() - started, 0.1)
|
||||
self.assertFalse(pool.is_loading("slow"))
|
||||
|
||||
deadline = time.monotonic() + 3
|
||||
while process.poll() is None and time.monotonic() < deadline:
|
||||
pool.poll()
|
||||
time.sleep(0.02)
|
||||
self.assertIsNotNone(process.poll())
|
||||
pool.poll()
|
||||
self.assertEqual(pool._stopping, []) # type: ignore[attr-defined]
|
||||
assert process.stdout is not None
|
||||
self.assertTrue(process.stdout.closed)
|
||||
|
||||
def test_query_pool_times_out_without_blocking_other_results(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
slow_ssh = Path(directory) / "ssh"
|
||||
|
||||
Reference in New Issue
Block a user