smodusermc/offline-games / _tools /run_isolated.py
smodusermc's picture
download
raw
2.2 kB
"""Run one game verification per child process with a memory and elapsed-time watchdog."""
import os,sys,time,signal,subprocess,shutil,json
from pathlib import Path
import psutil
R=Path('/home/user/game-archive/reports');T=R.parent/'tools'
for ident in map(int,sys.argv[1:]):
out=R/f'verification-{ident:04d}.json'
log=R/f'verification-{ident:04d}.log'
with log.open('w') as stream:
p=subprocess.Popen([sys.executable,str(T/'verify_games.py'),str(ident)],env=os.environ,stdout=stream,stderr=subprocess.STDOUT,start_new_session=True)
start=time.monotonic();reason=None;peak=0;rss_limit=int(os.environ.get('VERIFY_RSS_MIB','1350'));time_limit=int(os.environ.get('VERIFY_SECONDS','95'))
while p.poll() is None:
try:
proc=psutil.Process(p.pid);rss=sum(x.memory_info().rss for x in [proc]+proc.children(recursive=True) if x.is_running());peak=max(peak,rss)
except (psutil.NoSuchProcess,psutil.AccessDenied):rss=0
if rss>rss_limit*1024**2:reason=f'Test processes exceeded the {rss_limit} MiB summed RSS safety limit';break
if psutil.virtual_memory().available<160*1024**2:reason='Host available memory fell below 160 MiB';break
if time.monotonic()-start>time_limit:reason=f'Per-game verification exceeded the {time_limit}-second safety limit';break
time.sleep(.25)
if reason:
try:os.killpg(p.pid,signal.SIGKILL)
except ProcessLookupError:pass
p.wait(timeout=10)
manifest=json.loads((R/f'game-{ident}.json').read_text())
note={'id':ident,'name':manifest['name'],'entry':manifest['entry'],'status':'runtime_test_inconclusive_resource_limit','reason':reason,'peak_process_rss_bytes':peak,'gameplay_verified':False,'note':'Test was interrupted. Existing uploaded files remain; this does not establish a defect in the game.'}
out.write_text(json.dumps(note,indent=2))
elif not out.exists():
out.write_text(json.dumps({'id':ident,'status':'verification_process_failed','exit_code':p.returncode},indent=2))
shutil.rmtree(os.environ.get('GAME_VERIFY_STAGE','/tmp/game-verify-stage'),ignore_errors=True)
result=json.loads(out.read_text());print(ident,result['status'],'peak RSS MiB',round(peak/1048576),'seconds',round(time.monotonic()-start),flush=True)

Xet Storage Details

Size:
2.2 kB
·
Xet hash:
8e972331c61b6e99fec54019d3ed0beb980ac551333ea399fdc1f59d187d8e6c

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.