File indexing completed on 2026-11-09 10:47:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 set -u
0029 HERE=$(pwd)
0030 source ./replay.env
0031 mkdir -p run state out tmp gdb
0032
0033 cp environment-replay.sh run/
0034 SOCK=/tmp/esreplay-$$.sock
0035 export EPICPROD_SKIP_EVENTS="${REPLAY_SKIP}" EPICPROD_CHUNK_LABEL="${REPLAY_LABEL}"
0036 export EPICPROD_SIM_SOCKET="${SOCK}" EPICPROD_SIM_STATE="${HERE}/state"
0037 export EPICPROD_SIM_REPLY="${HERE}/out/simulation.json"
0038 export EPICPROD_UNIT_TEMPLATE="${HERE}/out/unit-template.json"
0039 export EPICPROD_CALL_HOME=0 EPICPROD_NTHREADS=1 REGISTRATION_STAGGER_MAX_S=0
0040
0041
0042 export TMPDIR="${HERE}/tmp"
0043 export PAYLOAD_STAGES_LOG="${HERE}/out/stages.log" PAYLOAD_REPORT="${HERE}/out/payload-report.json"
0044 export PAYLOAD_JOB_REPORT="${HERE}/out/jobReport.json"
0045
0046 started=$(date +%s)
0047 echo "replay: run.sh ${REPLAY_FILE} ${REPLAY_EXT} ${REPLAY_EVENTS} ${REPLAY_CHUNK}, skip ${REPLAY_SKIP}, label ${REPLAY_LABEL:-none}"
0048 (cd run && timeout "${REPLAY_TIMEOUT_S}" "${HERE}/payload/run.sh" \
0049 "${REPLAY_FILE}" "${REPLAY_EXT}" "${REPLAY_EVENTS}" "${REPLAY_CHUNK}") > out/payload.log 2>&1
0050 rc=$?
0051 ended=$(date +%s)
0052 echo "replay: run.sh exited ${rc} after $((ended - started)) s"
0053
0054
0055 (cd payload/es && python3 -c 'import sys; from resident_sim import exchange; exchange(sys.argv[1], {"command": "stop"}, 10)' \
0056 "${SOCK}") > /dev/null 2>&1 || true
0057 pkill -f -- "--socket ${SOCK}" 2>/dev/null || true
0058
0059
0060
0061
0062
0063 signal=$(grep -oE 'Handle signal: (6|7|8|11)\b' state/resident.log 2>/dev/null | head -1 | grep -oE '[0-9]+$')
0064 gdb_rc=""
0065 if [ -n "${signal}" ] && [ -s out/unit-template.json.npsim.json ]; then
0066
0067
0068 if python3 - out/unit-template.json.npsim.json gdb > gdb/args.log 2>&1 <<'EOF'
0069 import json, os, sys
0070 argv, d = json.load(open(sys.argv[1])), sys.argv[2]
0071 out, source, i = [], '', 0
0072 while i < len(argv):
0073 flag = argv[i]
0074 if flag == '--random.enableEventSeed':
0075 i += 1
0076 continue
0077 if flag in ('--skipNEvents', '--inputFiles', '--outputFile'):
0078 value = argv[i + 1]
0079 if flag == '--inputFiles':
0080 source = value
0081 value = os.path.abspath(os.path.join(d, 'range.hepmc3'))
0082 elif flag == '--skipNEvents':
0083 value = '0'
0084 else:
0085 value = os.path.abspath(os.path.join(d, 'out.edm4hep.root'))
0086 out += [flag, value]
0087 i += 2
0088 continue
0089 out.append(flag)
0090 i += 1
0091 seed = argv[argv.index('--random.seed') + 1] if '--random.seed' in argv else ''
0092 if seed != os.environ.get('REPLAY_SEED'):
0093 sys.exit(f'request seed {seed} is not the recorded {os.environ.get("REPLAY_SEED")}')
0094 open(os.path.join(d, 'source'), 'w').write(source)
0095 open(os.path.join(d, 'args'), 'w').write('\0'.join(out))
0096 print('cold npsim arguments:', ' '.join(out))
0097 EOF
0098 then
0099 python3 payload/es/evgen_ranges.py --input "$(cat gdb/source)" --first-event "${REPLAY_SKIP}" \
0100 --events "${REPLAY_EVENTS}" --output gdb/range.hepmc3 > gdb/cut.log 2>&1
0101 cut_rc=$?
0102 if [ "${cut_rc}" -eq 0 ]; then
0103 mapfile -d '' args < gdb/args
0104 npsim_py="$(dirname "$(readlink -f "$(command -v npsim)")")/npsim.py"
0105 (cd run && timeout "${REPLAY_TIMEOUT_S}" gdb -batch -ex run -ex bt -ex 'info registers rip' \
0106 --args python3 "${npsim_py}" "${args[@]}") > out/gdb.log 2>&1
0107 gdb_rc=$?
0108 else
0109 echo "replay: the range cut failed (exit ${cut_rc}); see gdb/cut.log"
0110 fi
0111 fi
0112 fi
0113
0114 python3 - "${rc}" "${signal}" "${started}" "${ended}" "${gdb_rc}" > out/result.json.tmp <<'EOF'
0115 import json, os, socket, sys
0116 rc, signal, started, ended, gdb_rc = sys.argv[1:6]
0117 def read(path):
0118 try:
0119 with open(path) as f:
0120 return f.read()
0121 except OSError:
0122 return ''
0123 reply = {}
0124 try:
0125 reply = json.loads(read('out/simulation.json') or '{}')
0126 except ValueError:
0127 pass
0128 stages = read('out/stages.log').strip().splitlines()
0129 gdb = read('out/gdb.log')
0130 stopped = next((l.split('Program received signal', 1)[1].strip().rstrip('.')
0131 for l in gdb.splitlines() if 'Program received signal' in l), '')
0132 resident = read('state/resident.log')
0133 stalled = signal and 'Handle signal: 15' in resident
0134 if signal:
0135 outcome, reason = 'crashed', f'resident npsim died on signal {signal}' + (
0136 ', stalled after it and was killed at the request timeout' if stalled else '')
0137 elif reply and not reply.get('error'):
0138 outcome, reason = 'completed', ''
0139 else:
0140 outcome = 'inconclusive'
0141 reason = (f'run.sh exited {rc}' + (' (timed out)' if rc == '124' else '')
0142 + (' after the resident was killed at the request timeout with no crash signal'
0143 if 'Handle signal: 15' in resident else ' with no simulation reply and no resident death')
0144 + (f'; last stage: {stages[-1]}' if stages else ''))
0145 json.dump({'outcome': outcome, 'reason': reason, 'signal': int(signal) if signal else None,
0146 'payload_exit': int(rc), 'started_at': int(started), 'ended_at': int(ended),
0147 'host': socket.gethostname().split('.')[0],
0148 'simulation_reply': {k: reply.get(k) for k in ('events', 'seed', 'first_event',
0149 'seed_mode', 'wall_s', 'error') if k in reply},
0150 'gdb': {'ran': bool(gdb), 'rc': int(gdb_rc) if gdb_rc else None, 'stopped_on': stopped},
0151 'stages': stages[-8:]}, sys.stdout, indent=1)
0152 EOF
0153 mv -f out/result.json.tmp out/result.json
0154 echo "replay: result written"