feat(mosstank): add VTank-style automation PoC
This commit is contained in:
parent
f6fe0f2a4f
commit
4e6e9bc9d9
212 changed files with 49462 additions and 416 deletions
|
|
@ -24,6 +24,79 @@ What does NOT go here:
|
|||
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
|
||||
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
|
||||
|
||||
## #451 — GLFW can dereference another acdream process's private window pointer after cross-process activation
|
||||
|
||||
**Status:** IN-PROGRESS — exact root fixed; 100-switch/30-minute dual-client
|
||||
stress passed 2026-08-27. Graceful exit of both sessions remains before closure.
|
||||
**Component:** graphical host / GLFW Win32 event pump / multi-process stability.
|
||||
**Severity:** HIGH for multi-account play; one of the two sessions is lost without
|
||||
an orderly disconnect.
|
||||
|
||||
Running two copies of the exact isolated `app-release23` graphical artifact
|
||||
against local ACE reproduced the same access violation three times. The
|
||||
faulting process varied: secondary PID 13688 at 15:01:39, primary PID 15300 at
|
||||
15:03:35, and fresh primary PID 31412 at 15:08:58. The last occurrence fired
|
||||
while the fresh primary was still on character selection, before EnterWorld;
|
||||
the already-in-world secondary survived. Windows Application Error reports
|
||||
all three as `coreclr.dll` exception `0xC0000005`, fault offset `0x356d4f`.
|
||||
The managed terminal stack is only:
|
||||
|
||||
```text
|
||||
Silk.NET.Windowing.WindowExtensions...Run
|
||||
Silk.NET.Windowing.Internals.ViewImplementationBase.Run
|
||||
Silk.NET.Windowing.Glfw.GlfwWindow.Run
|
||||
AcDream.App.Rendering.GameWindow.Run
|
||||
```
|
||||
|
||||
This is not #422's rare `0xC0000374` heap corruption during graceful process
|
||||
exit: #451 happens while both graphical clients are active and reproduces
|
||||
quickly. It is also not a MossTank/plugin-API, CoreCLR, Vulkan, PAK, or world-
|
||||
cache failure.
|
||||
|
||||
**Exact root (first-chance cdb proof):** the access violation is in packaged
|
||||
GLFW's Win32 event pump at `glfw3+0x10681`, not in CoreCLR. During its modifier-
|
||||
key repair pass `_glfwPollEventsWin32` calls `GetActiveWindow`, then
|
||||
`GetPropW(hwnd, L"GLFW")`, and dereferences the returned value as this
|
||||
process's `_GLFWwindow*`. Windows UI automation temporarily joins input queues,
|
||||
so the primary process can receive the secondary process's HWND. Because every
|
||||
GLFW process uses the same `GLFW` property name, `GetPropW` succeeds but returns
|
||||
the secondary process's private pointer. The crashed primary had
|
||||
`rbx=00000202a7180ab0`; a debugger breakpoint in the surviving secondary
|
||||
reported its own valid `ACTIVE_GLFW_WINDOW=00000202a7180ab0` — exact pointer
|
||||
identity across the process boundary.
|
||||
|
||||
**Fix:** `Win32GlfwActiveWindowGuard` patches only `glfw3.dll`'s import-address-
|
||||
table slot for `USER32!GetActiveWindow`, after the GLFW library is loaded and
|
||||
before `glfwInit`/window creation. The replacement returns the real HWND only
|
||||
when `GetWindowThreadProcessId` says it belongs to the current process;
|
||||
otherwise it returns zero, GLFW's existing safe "nothing to repair" branch.
|
||||
There is no system-wide hook and no other module is changed. Four focused
|
||||
tests cover local, foreign, null and unowned HWNDs.
|
||||
|
||||
The isolated `app-release24` live gate launched two graphical clients, both
|
||||
logged `GLFW foreign-active-window guard installed (#451)`, entered the world,
|
||||
and remained responsive through 100 rapid forced cross-process activation
|
||||
switches — the exact prior trigger — plus a 30-minute combined in-world soak.
|
||||
The local peer API then passed in both directions: the secondary evaluated the
|
||||
primary heartbeat and returned `+Acdream`. A two-member fellowship gate also
|
||||
passed with both canonical rosters populated and the secondary returning `2`
|
||||
from `getfellowshipcount[]`; both processes remained alive and responsive.
|
||||
|
||||
Evidence:
|
||||
|
||||
- `artifacts/live-gates/mosstank-final23-secondary/`
|
||||
- `artifacts/live-gates/mosstank-final23-secondary2/`
|
||||
- `artifacts/live-gates/mosstank-final23-primary5/`
|
||||
- `artifacts/live-gates/i451-cdb-primary-attach/cdb.log`
|
||||
- `artifacts/live-gates/i451-cdb-secondary/cdb.log`
|
||||
- `artifacts/live-gates/i451-guard-primary2/`
|
||||
- `artifacts/live-gates/i451-guard-secondary/`
|
||||
- Windows Application Error events at 2026-08-27 15:01:39, 15:03:35 and
|
||||
15:08:58 (same module, exception and offset).
|
||||
|
||||
**Next:** close only after both `app-release24` sessions exit gracefully; the
|
||||
activation and sustained in-world portions of the regression gate have passed.
|
||||
|
||||
## #450 — Fast character re-entry after logout can remain in portal space at `lb 0/0`
|
||||
|
||||
**Status:** DONE — OWNER-ACCEPTED 2026-08-26 in the combined client-parity gate.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue