Files
RP412/tools/podium-repro/setup.ps1
T
CydandClaude Opus 5 6467a5f930 The teardown looks at the segments before it calls through them
The podium crash dies in SocketIterator::DeletePlugs, calling through a
segment whose vtable dword has been replaced by a small float. The three
dumps prove the segment is wrong BY teardown; nothing in them says when
it went wrong, and six configurations of the local repro rig - parked
pods, driven pods, light and full page heap, two, four and six pods -
reached the podium and tore down clean.

So the next real playtest becomes the instrument. RP412SEGCHECK walks
the segment table in ~JointedMover before the delete, guarded-reads each
segment's first dword, and if one does not match the vtable captured
from the very first segment ever built it writes the forensics into
rpl4-fail.log, which is closed on the way down and survives the abort -
rpl4.log does not. The report carries the entity and whether it was the
local pod, which index went bad and what is in it, the first two rows of
the object as hex and float, and the heap deltas to its neighbours on
either side.

Three bracket calls in the winners' circle answer the question the dumps
cannot: at podium entry, and either side of the second
MakeEntityRenderables on the own pod. Whichever fires first is recorded
and travels inside the teardown report, so the log says whether the race
broke the segment or the podium did.

It deliberately does not skip the delete or repair the pointer. The
ownership bug is unfixed and a guard would cost exactly the evidence
this is here to collect - it stops on the same object, one step earlier,
holding the forensics. On by default, a handful of pointer compares per
pod per race; RP412SEGCHECK=0 turns it off, and the environ.ini template
says so.

tools/podium-repro is the rig itself, banked with what the dumps already
established: page heap turned on through the PEB without gflags or
elevation, N sandboxed installs, and a feeder that drives full races
through them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 16:33:31 -05:00

71 lines
2.9 KiB
PowerShell

# Builds the sandboxed pod installs for the podium-teardown repro.
# Assets are junctioned from dist, the exe comes from Release (build first).
# Use the SAME -PodCount you intend to pass to feeder.ps1.
param(
[ValidateRange(2, 8)]
[int]$PodCount = 2,
[string]$Scratch = "$env:TEMP\rp412-podium-repro",
[string]$Dist = 'C:\VWE\RP412\dist',
[string]$ReleaseExe = 'C:\VWE\RP412\Release\rpl4opt.exe',
# Drive the pods into things so the race contains damage, deaths and
# respawns. Parked pods reach the podium and tear down clean; the fatal
# playtest's pods did not. -Drive 0 restores the sterile run.
[int]$Drive = 1
)
$ErrorActionPreference = 'Stop'
if (-not (Test-Path $ReleaseExe)) { throw "build Release first: $ReleaseExe missing" }
New-Item -ItemType Directory -Force $Scratch | Out-Null
for ($i = 0; $i -lt $PodCount; $i++) {
$dir = "$Scratch\pod$([char](65 + $i))"
New-Item -ItemType Directory -Force $dir | Out-Null
foreach ($assets in 'AUDIO','GAUGE','VIDEO') {
if (-not (Test-Path "$dir\$assets")) {
New-Item -ItemType Junction -Path "$dir\$assets" -Target "$Dist\$assets" | Out-Null
}
}
foreach ($file in 'environ.ini','JOYSTICK.INI','RPDPL.INI','RPL4.RES','libsndfile-1.dll','OpenAL32.dll') {
Copy-Item "$Dist\$file" $dir -Force
}
Copy-Item $ReleaseExe $dir -Force
#
# dist ships RP412PODIUM=0 - the podium is OFF by default, and a rig that
# copies environ.ini verbatim tests nothing (every pod just logs
# "WinnersCircle: disabled" and goes straight to the results). Force it on.
#
# Appended, not edited: environ.ini takes the LAST value for a duplicate
# key. Written as ASCII with no BOM - a BOM in this file has invalidated
# test runs before.
#
$override = "`r`n# --- podium-repro overrides (setup.ps1) ---`r`nRP412PODIUM=1`r`n"
if ($Drive -ne 0) {
Copy-Item "$PSScriptRoot\crashlap.txt" $dir -Force
$override += "RP412INPUTSCRIPT=crashlap.txt`r`n"
}
[IO.File]::AppendAllText("$dir\environ.ini", $override, [Text.Encoding]::ASCII)
}
#
# Retire evidence from pods this run will not use. A -PodCount 2 run after a
# -PodCount 6 run leaves podC..podF holding the SIX-pod logs and dumps, and
# a grep across the tree then reports results that belong to a different
# experiment - which has already caused one wrong reading.
#
# Files only, never the directories: they contain junctions to the dist
# asset folders, and a recursive delete through a junction can take the
# TARGET's contents with it.
#
for ($i = $PodCount; $i -lt 8; $i++) {
$k = [char](65 + $i)
$stale = @(
"$Scratch\pod$k\rpl4.log"
"$Scratch\pod$k\podbreak*.dmp"
"$Scratch\pod$k-cdb.log"
)
Remove-Item $stale -Force -Confirm:$false -ErrorAction SilentlyContinue
}
foreach ($file in 'runpod.cmd','cdbrun.txt','cdbrun-gflags.txt','feeder.ps1') {
Copy-Item "$PSScriptRoot\$file" $Scratch -Force
}
Write-Output "$PodCount pod sandboxes ready under $Scratch"