from __future__ import annotations import argparse import signal import subprocess import time from common import touch_ready, wait_for_tcp def main() -> int: ap = argparse.ArgumentParser(description="Seed a fixture with aria2.") ap.add_argument("--torrent", required=True) ap.add_argument("--data", required=True) ap.add_argument("--port", type=int, required=True) args = ap.parse_args() cmd = [ "aria2c", "--dir", args.data, "--seed-time=1000000", "--check-integrity=true", "--allow-overwrite=false", "--auto-file-renaming=false", "--enable-dht=false", "--enable-dht6=false", "--enable-peer-exchange=false", "--bt-enable-lpd=false", "--listen-port", str(args.port), "--dht-listen-port", str(args.port), "--summary-interval=0", args.torrent, ] proc = subprocess.Popen(cmd) stop = False def _stop(signum, frame): nonlocal stop stop = True proc.terminate() signal.signal(signal.SIGTERM, _stop) signal.signal(signal.SIGINT, _stop) try: wait_for_tcp("127.0.0.1", args.port, timeout=45) if proc.poll() is not None: return proc.returncode or 1 # aria2 may still be checking files; the runner also has retry/timeout, # so readiness here means the peer port is accepting connections. touch_ready() print(f"aria2 seeding on {args.port}", flush=True) while not stop and proc.poll() is None: time.sleep(1) return proc.returncode or 0 finally: if proc.poll() is None: proc.terminate() try: proc.wait(timeout=10) except subprocess.TimeoutExpired: proc.kill() if __name__ == "__main__": raise SystemExit(main())