fix(streaming): #339 — a packed EnvCell geom id no longer misroutes into the 32-bit prepare arm
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
The reveal hang (three live occurrences: portal-space, login twice) was an unhandled OverflowException on the render frame's readiness evaluation: EnsureRenderDataReady found a packed 64-bit EnvCell geometry id OWNED but DESCRIPTOR-LESS — the release path removes the descriptor while render data parks on the LRU, IncrementRefCount restores ownership on a revisit, and the scheduler's PrepareEnvCellGeomMeshDataAsync has not yet re-registered — and fell through to the Setup/GfxObj arm, whose checked((uint)id) cast threw. After that the reveal was never evaluated again. The fix corrects the TYPE DISPATCH rather than suppressing anything: packed ids (bit 33, GetEnvCellGeomId) answer "not yet" in the acquire-to-prepare window — the true answer, since the scheduler re-registers on the same landblock build — and PrepareMeshDataAsync's blind cast becomes a typed, loud invariant failure naming the id kind and the issue, so a future caller repeating the confusion gets a diagnosis instead of three live hangs. Validation: the crash was DETERMINISTIC at login cell 0xA8B4002F (two consecutive hard failures); with the fix the same login revealed cleanly and a full session — 16,585 entities, five portal generations, the user-passed Session-B dungeon gate — ran with zero overflows and zero guard fires. Clean-room suite: 11,253 passed / 6 skipped / 0 failed. Found because the Session-B gate launch finally captured the stack the earlier #339 hangs never printed. #343 (the wounded loop's Reset-in- render-loop shutdown) and #344 (the mid-teleport world-frame race the same evening surfaced) are filed separately and unfixed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
42de5f18ff
commit
205379c6d6
2 changed files with 51 additions and 1 deletions
|
|
@ -1071,6 +1071,25 @@ namespace AcDream.App.Rendering.Wb
|
|||
EnvCellGeomRequest? envCell = _envCellDescriptors.TryGetValue(id, out EnvCellGeomRequest descriptor)
|
||||
? descriptor
|
||||
: null;
|
||||
// #339: the same type contract, stated loudly at the second
|
||||
// entry. A packed EnvCell geometry id (bit 33) must arrive
|
||||
// with its descriptor; reaching the Setup/GfxObj arm with one
|
||||
// is caller type confusion, and the bare checked-cast
|
||||
// OverflowException it used to produce cost three live hangs
|
||||
// before it was diagnosable.
|
||||
if (envCell is null && id > uint.MaxValue)
|
||||
{
|
||||
var confused = new InvalidOperationException(
|
||||
$"Packed EnvCell geometry id 0x{id:X16} reached the "
|
||||
+ "Setup/GfxObj preparation arm without a registered "
|
||||
+ "descriptor (#339). Callers must route packed ids "
|
||||
+ "through PrepareEnvCellGeomMeshDataAsync or treat "
|
||||
+ "them as not-ready until the scheduler registers "
|
||||
+ "them.");
|
||||
tcs.TrySetException(confused);
|
||||
_terminalPreparationFailures.Add(id);
|
||||
return task;
|
||||
}
|
||||
PreparedAssetRequest asset = envCell is { } env
|
||||
? PreparedAssetRequest.EnvCellGeometry(
|
||||
env.SourceCellId,
|
||||
|
|
@ -1327,6 +1346,23 @@ namespace AcDream.App.Rendering.Wb
|
|||
req.CellStructure,
|
||||
req.Surfaces);
|
||||
}
|
||||
else if (id > uint.MaxValue)
|
||||
{
|
||||
// #339 (2026-08-07): a PACKED EnvCell geometry id (bit 33 set,
|
||||
// GetEnvCellGeomId) whose descriptor is not registered — the
|
||||
// acquire→prepare window of a demote-then-revisit cycle:
|
||||
// release removed the descriptor, IncrementRefCount restored
|
||||
// ownership on the revisit, and the scheduler's
|
||||
// PrepareEnvCellGeomMeshDataAsync (which re-registers it with
|
||||
// full data on every landblock build) has not run yet. The
|
||||
// honest readiness answer is simply "not yet" — the prepare
|
||||
// arrives on the same build. Falling through to the 32-bit
|
||||
// Setup/GfxObj arm was a TYPE CONFUSION whose checked cast
|
||||
// threw OverflowException on the render frame's readiness
|
||||
// evaluation, after which the reveal was never evaluated
|
||||
// again: the login/portal hang the user hit three times.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = PrepareMeshDataAsync(id, isSetup: false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue