docs: VF-01 confirmed (worker race on rebuild) + VF-10 triaged; hold further code
VF-01 CONFIRMED and it is the most serious find of the day. Initialize does StrateLayout.Empty() and Passages.Empty()/Add() -- freeing and reallocating both -- with no lock, barrier or drain anywhere in that file, while worker threads read the same arrays through AnyPassageNearBox (:460), EvaluateModifierSDF and FindSlotIndexForChunkZ, reached from GetDensityAt/ClassifyTile. RegenerateAllChunks bumps the epoch AFTER the mutation, so previous-epoch workers are live during it; the epoch rejects a finished result, it cannot make a read of a freed allocation safe. Same class already fixed once here: DiffLayer.ChunkMods got ModsLock after a carve-vs-stream AV. The dangerous call site is OnObjectModifiedInEditor, which fires automatically on a strate asset edit while streaming -- routine here. VF-10 confirmed real (74 fields, per near-surface sample) but Sol missed the conclusion: the copy is INHERITED from GetDensityWithParams, so both paths pay it and it does NOT explain the op-stack regression. The op stack improved it by memoising across eleven detail ops. Future optimisation, not the answer. Deliberately NOT fixing VF-01 now. Four code changes are stacked unbuilt and three have "nothing should move" as their acceptance signal; a fifth change to streaming lifecycle would make an odd build result unattributable. The three fix options (drain / snapshot / RWLock) trade a possible crash for an editor hitch or hot-path lock traffic -- a product decision, not an agent's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,9 @@
|
||||
> | **VF-05** (radius envelope in `BuildChunkCache`) | ✅ **CONFIRMED and FIXED** — `CODEX-TASK-006`. Real, and the worst of three instances of this class: it is `TunnelNetwork`, it is in code **both** density paths share, and it breaks window invariance (`ARCHITECTURE §8.4`). Genuinely good find. |
|
||||
> | **VF-02** (3-second shutdown timeout) | ✅ **premise confirmed** — `VoxelWorld.cpp:327` literally reads *"Timeout after 3 seconds to avoid hanging the editor."* Note `CLAUDE.md` states the invariant more strongly than the code implements it ("EndPlay blocks on `ActiveTaskCount → 0`" — it blocks *with a deadline*). Worth deciding deliberately. |
|
||||
> | **VF-03** (TLS caches omit the owning world) | ⚠️ **substance plausible, EVIDENCE OVERSTATED.** It claims *"the test fixture explicitly documents observed cross-world contamination."* It does not. `VoxelForgeTestFixture.h` documents that the `thread_local` caches exist and flags an unrelated `TSoftObjectPtr` risk. The underlying point (caches keyed on chunk/seed/layout but not on which generator owns them) may still hold — but it needs checking on its own merits, not on this citation. |
|
||||
> | VF-01, VF-04, VF-06 … VF-10 | **NOT independently verified.** Read them as leads. |
|
||||
> | **VF-01** (live rebuild races streaming workers) | ✅ **CONFIRMED — the most serious finding here.** `UVoxelStrateManager::Initialize` does `StrateLayout.Empty()` (:~36) **and** `Passages.Empty()` (:171) then `Passages.Add()`, i.e. it frees and reallocates both arrays. There is **no lock, no barrier, no drain** anywhere in that file. Worker-side readers of the same arrays: `AnyPassageNearBox` (:460, range-for over `Passages`), `EvaluateModifierSDF` (indexes `Passages[...]`), `FindSlotIndexForChunkZ` (iterates `StrateLayout`) — all reached from `GetDensityAt`/`ClassifyTile` on mesher workers. And `RegenerateAllChunks()` (which bumps the epoch) runs **after** `Initialize`, so previous-epoch workers are still live during the mutation. **This is the same class already fixed once in this codebase** — `DiffLayer.ChunkMods` got `ModsLock` after a carve-vs-stream access violation. Four call sites, incl. `OnObjectModifiedInEditor` (:309), which fires automatically when a strate asset is edited while the world streams. **NOT fixed — see the note below.** |
|
||||
> | **VF-10** (~74-field per-voxel params copy) | ✅ **confirmed real, but Sol missed the conclusion that matters.** The 74 fields are real and the copy is per near-surface sample. **However it is INHERITED from the original path — `GetDensityWithParams` does the same copy — so both paths pay it equally and it does NOT explain the op-stack perf regression.** The op stack actually *improved* it (memoised so eleven detail ops don't each repeat it), and the site says so in its own comment. Genuine future optimisation for both paths; **not** the answer to "why is the op path slower". |
|
||||
> | VF-04, VF-06, VF-07, VF-08, VF-09 | **NOT independently verified.** Read them as leads. |
|
||||
>
|
||||
> **Do not treat an unverified row as actionable.** The lesson this project keeps paying for is that a
|
||||
> confident chain resting on an unchecked premise reverses about half the time — and VF-03 is an
|
||||
|
||||
Reference in New Issue
Block a user