mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
fix: unwind a terminated run to drop its scratch
This commit is contained in:
1 parent
9b08925dd0
commit
af3c90e448
2 files changed
+51
No files matched your search
@@ -15,6 +15,7 @@ import functools
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import sys
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
@@ -3564,6 +3565,10 @@ from dumpcatalog import ( # noqa: E402,F401
|
||||
)
|
||||
|
||||
|
||||
def _exit_on_signal(signum: int, _frame: object) -> None:
|
||||
sys.exit(128 + signum)
|
||||
|
||||
|
||||
def run_cli(main: Callable[[], int | None]) -> None:
|
||||
"""Run a command-line entry point to its exit status.
|
||||
|
||||
@@ -3571,7 +3576,15 @@ def run_cli(main: Callable[[], int | None]) -> None:
|
||||
and the next write died on a BrokenPipeError traceback. Output nobody
|
||||
reads any more ends the run quietly, with the status a shell gives a
|
||||
writer whose reader left.
|
||||
|
||||
SIGTERM (timeout, kill) and SIGHUP (a closed terminal) end the process
|
||||
without unwinding by default: a pack build left its multi-GB hidden
|
||||
.partial behind. Raised as SystemExit, they run the cleanup a failed
|
||||
write runs, and the status stays the one a shell gives the signal.
|
||||
"""
|
||||
for name in ("SIGTERM", "SIGHUP"):
|
||||
if hasattr(signal, name):
|
||||
signal.signal(getattr(signal, name), _exit_on_signal)
|
||||
try:
|
||||
code = main()
|
||||
sys.stdout.flush()
|
||||
|
||||
@@ -296,5 +296,43 @@ class RestoreSkipsDownloadsInProgress(unittest.TestCase):
|
||||
self.assertIn(str(cache / "done.bin"), index.values())
|
||||
|
||||
|
||||
class ATerminatedBuildLeavesNoScratch(unittest.TestCase):
|
||||
"""`timeout 120 generate_pack.py --platform RetroArch` left a 3.4 GB
|
||||
hidden .partial in dist/: SIGTERM ended the process without running the
|
||||
cleanup a failed write runs."""
|
||||
|
||||
CHILD = (
|
||||
"import sys, time\n"
|
||||
"sys.path.insert(0, 'scripts')\n"
|
||||
"from common import run_cli\n"
|
||||
"from generate_pack import _writing_pack\n"
|
||||
"def main():\n"
|
||||
" with _writing_pack(sys.argv[1]) as zf:\n"
|
||||
" zf.writestr('a.bin', b'x')\n"
|
||||
" print('writing', flush=True)\n"
|
||||
" time.sleep(60)\n"
|
||||
"run_cli(main)\n"
|
||||
)
|
||||
|
||||
def test_sigterm_removes_the_partial_pack(self):
|
||||
import signal # noqa: PLC0415
|
||||
import subprocess # noqa: PLC0415
|
||||
|
||||
if not hasattr(signal, "SIGTERM") or os.name != "posix":
|
||||
self.skipTest("POSIX signals")
|
||||
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
|
||||
pack = Path(tmp) / "Demo_BIOS_Pack.zip"
|
||||
child = subprocess.Popen(
|
||||
[sys.executable, "-c", self.CHILD, str(pack)], cwd=REPO_ROOT,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
|
||||
)
|
||||
self.assertEqual(child.stdout.readline().strip(), "writing")
|
||||
self.assertTrue(list(Path(tmp).glob(".*.partial")))
|
||||
child.send_signal(signal.SIGTERM)
|
||||
child.communicate(timeout=60)
|
||||
self.assertEqual(child.returncode, 128 + signal.SIGTERM)
|
||||
self.assertEqual(sorted(p.name for p in Path(tmp).iterdir()), [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user