Pin OMP_DYNAMIC=FALSE so thread counts stay deterministic, record it in the command line, and locate the binary hash correctly when the command is wrapped in env with inline assignments.
55 lines
2.4 KiB
Python
55 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Logged, serial, bounded command runner. A timeout stops this invocation."""
|
|
import hashlib
|
|
import fcntl
|
|
import os
|
|
from pathlib import Path
|
|
import shlex
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
root = Path(__file__).resolve().parents[2]
|
|
def run(name, command, seconds=45):
|
|
guard=open('/tmp/gr_psf_replay.lock','w')
|
|
fcntl.flock(guard,fcntl.LOCK_EX|fcntl.LOCK_NB)
|
|
running=subprocess.check_output(['ps','-eo','pid=,comm='],text=True)
|
|
names={'replay_psf','capture_psf','benchmark_hip_p','test_hip_psf','minkowski_sky','minkowski_sky_h','schwarzschild_s'}
|
|
conflicts=[line for line in running.splitlines() if line.split()[-1] in names]
|
|
if conflicts:raise RuntimeError('another test/render is running: '+str(conflicts))
|
|
logfile = Path(__file__).parent / (name + '.log')
|
|
if logfile.exists():
|
|
raise RuntimeError(f'refusing to overwrite {logfile}')
|
|
env = dict(os.environ, OMP_NUM_THREADS='16', OMP_DYNAMIC='FALSE')
|
|
with logfile.open('x') as out:
|
|
out.write('COMMAND OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE ' +
|
|
shlex.join(command) + '\n')
|
|
out.write(f'TIMEOUT {seconds}s\n')
|
|
out.write('GIT ' + subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True))
|
|
binary_index = 0
|
|
if command[0] == 'env':
|
|
binary_index = 1
|
|
while binary_index < len(command) and '=' in command[binary_index]:
|
|
binary_index += 1
|
|
binary = Path(command[binary_index]) if binary_index < len(command) else Path()
|
|
if binary.is_file():
|
|
out.write('BINARY_SHA256 ' + hashlib.sha256(binary.read_bytes()).hexdigest() + '\n')
|
|
out.flush()
|
|
start = time.monotonic()
|
|
p = subprocess.Popen(command,cwd=root,env=env,stdout=out,stderr=subprocess.STDOUT,start_new_session=True)
|
|
try:
|
|
status = p.wait(timeout=seconds)
|
|
except subprocess.TimeoutExpired:
|
|
os.killpg(p.pid, signal.SIGKILL)
|
|
p.wait()
|
|
out.write(f'TIMEOUT killed and reaped pid={p.pid}\n')
|
|
raise
|
|
out.write(f'PROCESS_WALL {time.monotonic()-start:.9f} EXIT {status}\n')
|
|
print(f"{name}: exit={status}; raw output: {logfile}", flush=True)
|
|
if status:
|
|
raise RuntimeError(f'{name} exit {status}; stop and inspect')
|
|
|
|
if __name__ == '__main__':
|
|
run(sys.argv[1], sys.argv[3:], int(sys.argv[2]))
|