From 75301ca84d8ee03f28f719ca8a255547fff402d9 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Fri, 5 Jun 2026 15:08:55 -0400 Subject: [PATCH] Test runner: retry the SQLite teardown on Windows PermissionError (local-only nicety) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On local Windows + SQLite, DiscoverRunner's teardown ends in os.remove(test_db.sqlite3), which raises PermissionError [WinError 32] when another handle still holds the file (a concurrent run, a lingering connection, AV / Search indexer) — crashing an otherwise-green run at the very end. RobustCompressorTestRunner.teardown_databases now retries super() up to 10x with a 0.1s sleep, then leaves the stale file for the next run to overwrite rather than fail. Mirrors the _robust_save PermissionError retry already in the runner. CI-neutral: CI is Postgres on Linux — teardown is DROP DATABASE (no file remove), and Linux unlinks open files without error — so the loop never triggers there. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/core/runner.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/core/runner.py b/src/core/runner.py index 2dc9327..4b7ec84 100644 --- a/src/core/runner.py +++ b/src/core/runner.py @@ -96,4 +96,21 @@ class RobustCompressorTestRunner(DiscoverRunner): "WHERE datname = %s AND pid <> pg_backend_pid()", [test_db_name], ) - super().teardown_databases(old_config, **kwargs) + # On local Windows + SQLite, super() ends in os.remove(test_db.sqlite3), + # which raises PermissionError [WinError 32] when another handle still + # holds the file (a concurrent run, a lingering connection, AV / Search + # indexer). Retry briefly, then leave the stale file for the next run to + # overwrite rather than crash an otherwise-green run. CI is Postgres on + # Linux — DROP DATABASE, no file remove, and Linux unlinks open files + # without error — so this loop never triggers there. Mirrors + # _robust_save's PermissionError retry. + for attempt in range(10): + try: + super().teardown_databases(old_config, **kwargs) + return + except PermissionError: + if attempt == 9: + print("teardown_databases: test DB file still locked after " + "retries — leaving it for the next run to overwrite.") + return + time.sleep(0.1)