You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reported by a partner integrator (Amazon Lab126 / LeiaViewer port, internal ticket UNITY-133).
2026-09-02 — SCOPE CORRECTED. This issue originally pooled six crash dumps under one signature. Investigation with the partner's agent established that they are at least three distinct bugs. This issue is now scoped to one: the main-thread stack overflow in dump Unity.exe.23896. The others are split out — see Not this bug below.
This bug: main-thread stack overflow (dump Unity.exe.23896)
Independently proven from the dump by the partner's agent, not inferred:
rsp == StackLimit — the stack is genuinely exhausted, not merely deep.
A 7,344-byte frame pair repeating — unbounded recursion, one frame pair per iteration.
Access violation in mono-2.0-bdwgc.dll writing the page just below rsp — mono's stack probe against the exhausted stack. A later dump re-faults inside mono's vectored exception handler, itself running on the already-dead stack.
No DisplayXR native frames on the crashing stack, and no managed exception logged.
Attribution correction
An earlier revision of this issue presented that triage under the heading "Reporter's dump triage". The partner's agent did not write it and has asked for that on the record. Their own dump report stated only the faulting module; the proof above came from their later, independent analysis. The heading was wrong about the source — the content stands for dump 23896 and is not a valid description of "the #264 crash" generally, which is what the split below fixes.
Leading hypothesis: a stale SR window subclass (not yet confirmed)
From the runtime engineer, based on a prior recorded observation (2026-08-17), not on this incident:
The SR SDK subclasses the weaver's HWND via SetWindowLongPtr(GWLP_WNDPROC) and looks its context up by window.
Benign form — the weaver context is destroyed at shutdown but the subclass is not removed. SR's wndproc stays in the chain; every message to that HWND hits it, finds no context, logs WeaverBaseImpl: no handler for this window, and passes on.
Fatal form — a new weaver is created on the same HWND while the stale subclass is installed. The chain becomes self-referencing: SR wndproc -> CallWindowProcA -> SR wndproc -> ... until the stack is gone. Presents as c000041d FATAL_USER_CALLBACK_EXCEPTION with ~2500 SimulatedRealityDirectX frames, and no [TERMINATE]/[EXIT], because it dies inside the user callback.
This would make the repeating frame pair native SR wndproc frames, not managed ones — worth stating plainly, because the "managed recursion" reading in the original triage is an interpretation of the repeat, not an identification of it. The symbol on the repeating frame decides this and has not yet been read.
Runtime PR #1012 already applies the correct discipline on the service path (flush retired DPs bound to a window before creating a new one; destroy-before-recreate; prefer rebinding via setWindowHandle). The Unity provider uses the in-process _handle path, so the open question is whether that discipline is applied there at all.
Field evidence gathered 2026-09-02 (plugin v2.16.0)
Signature C reproduced post-shutdown, non-fatally. After 12 LoadScene Home/Viewer cycles with a live session and a normal Play-stop — no scripted resizes, so not a layout artefact:
provider: GfxStop -> Lifecycle Stop -> Lifecycle Shutdown -> 0 further DisplayXR-PROV lines, ever
weaver: WeaverBaseImpl: no handler for this window - 46 lines over ~6 min, THEN STOPPED
pattern: groups of 3, ~3ms / ~3ms / ~100ms within a group, clusters every 5-30 s
editor: alive and healthy throughout; no escalation
Message-driven rather than frame-driven (an idle editor is not rendering at 60 fps), surviving complete provider shutdown, and self-limiting — all consistent with the benign form above. Historical fatal runs reached 5,955 lines of the same string and ended with the editor's main window gone.
Ruled out on the plugin side (source-verified, no rig time):
Candidate
Result
Managed code driving native after teardown
None possible.DisplayXRGameViewRehostWatcher.Poll and DisplayXRPreviewClose.Poll both return on !isPlaying (PreviewClose's only native call is behind that gate). DisplayXRDisplayFramingPreview is the one thing that starts at Play-stop and hooks per-camera render callbacks — but makes zero native calls.
Dead both sides — none in this plugin; partner grepped their Assets/, third-party, and PackageCache: zero hits.
Hypotheses tested and falsified
Recorded so they are not re-proposed:
Game-view resize during Play produces a texture realloc. 24 scripted resizes, 9 realloc cycles, no crash.
LoadScene during a live session reaching realloc from another direction. 12 loads, no crash — and a weak null: the pane size never changed, so reconcile_size() had nothing to reconcile and the path was hit once, not twelve times. The 2D/3D view-count switch alone (submit=1-view vs submit=2-view, same 1468x748) does not trigger a bridge reallocation.
Managed log-callback recursion. Zero hits in either tree.
Not this bug — split out
Dump
Signature
Issue
Crash_2026-09-01_0244
Unity analytics — GetRenderingResolution under DeviceInfoEvent::CollectExtraInfo under MainMessageLoop. 13 flat frames, no mono, no recursion; zero stack overflow/recursion hits in the whole log.
40000015 in AssetImportWorker6 — a different process; likely a fourth thing. Log pull pending.
TBD
Note for #282: the render-target layer is not ruled out there. It dies reading rendering resolution on a box where a DisplayXR session had been changing the render target. That is an observation, not a mechanism.
Next — in value order
Read the symbol on the repeating frame in Unity.exe.23896. Decides managed-vs-native recursion outright and ends the guessing.
GetWindowLongPtrW(hwnd, GWLP_WNDPROC) on the editor's main window after Lifecycle Shutdown, mapped to a module. If it lands in an SR module, the stale-subclass mechanism is confirmed. One call, non-invasive.
Is the SR module (and DisplayXRClient.dll) still mapped post-shutdown? If the subclass survives but the code does not, that is a dangling wndproc and the next message is fatal, not the 2500th.
Play, Stop, Play escalation test. If each cycle adds a subclass layer, the rate should escalate rather than reset. Cheap, reversible, and distinguishes stale-subclass from a stuck loop without needing the fatal event.
Does the in-process _handle path apply PR #1012's destroy-before-recreate discipline?
Trap: do not read SRSession handle count as evidence. It leaks unconditionally on this platform — monotonic +2 per 10 s on a fully idle box with no SR app attached (7.8k vs ~400-650 for siblings). Use it to exclude, never to implicate.
Related: displayxr-leia-plugin#217 (the neighbouring unbounded-burst string, Weaving is not possible because window handle is invalid).
Reported by a partner integrator (Amazon Lab126 / LeiaViewer port, internal ticket UNITY-133).
This bug: main-thread stack overflow (dump
Unity.exe.23896)Independently proven from the dump by the partner's agent, not inferred:
rsp == StackLimit— the stack is genuinely exhausted, not merely deep.mono-2.0-bdwgc.dllwriting the page just belowrsp— mono's stack probe against the exhausted stack. A later dump re-faults inside mono's vectored exception handler, itself running on the already-dead stack.Attribution correction
An earlier revision of this issue presented that triage under the heading "Reporter's dump triage". The partner's agent did not write it and has asked for that on the record. Their own dump report stated only the faulting module; the proof above came from their later, independent analysis. The heading was wrong about the source — the content stands for dump 23896 and is not a valid description of "the #264 crash" generally, which is what the split below fixes.
Leading hypothesis: a stale SR window subclass (not yet confirmed)
From the runtime engineer, based on a prior recorded observation (2026-08-17), not on this incident:
The SR SDK subclasses the weaver's HWND via
SetWindowLongPtr(GWLP_WNDPROC)and looks its context up by window.WeaverBaseImpl: no handler for this window, and passes on.SR wndproc -> CallWindowProcA -> SR wndproc -> ...until the stack is gone. Presents asc000041dFATAL_USER_CALLBACK_EXCEPTION with ~2500SimulatedRealityDirectXframes, and no[TERMINATE]/[EXIT], because it dies inside the user callback.This would make the repeating frame pair native SR wndproc frames, not managed ones — worth stating plainly, because the "managed recursion" reading in the original triage is an interpretation of the repeat, not an identification of it. The symbol on the repeating frame decides this and has not yet been read.
Runtime PR #1012 already applies the correct discipline on the service path (flush retired DPs bound to a window before creating a new one; destroy-before-recreate; prefer rebinding via
setWindowHandle). The Unity provider uses the in-process_handlepath, so the open question is whether that discipline is applied there at all.Field evidence gathered 2026-09-02 (plugin v2.16.0)
Signature C reproduced post-shutdown, non-fatally. After 12
LoadSceneHome/Viewer cycles with a live session and a normal Play-stop — no scripted resizes, so not a layout artefact:Message-driven rather than frame-driven (an idle editor is not rendering at 60 fps), surviving complete provider shutdown, and self-limiting — all consistent with the benign form above. Historical fatal runs reached 5,955 lines of the same string and ended with the editor's main window gone.
Ruled out on the plugin side (source-verified, no rig time):
DisplayXRGameViewRehostWatcher.PollandDisplayXRPreviewClose.Pollboth return on!isPlaying(PreviewClose's only native call is behind that gate).DisplayXRDisplayFramingPreviewis the one thing that starts at Play-stop and hooks per-camera render callbacks — but makes zero native calls.Camera.Render()inside a render callbacklogMessageReceivedetc.)Assets/, third-party, and PackageCache: zero hits.Hypotheses tested and falsified
Recorded so they are not re-proposed:
LoadSceneduring a live session reaching realloc from another direction. 12 loads, no crash — and a weak null: the pane size never changed, soreconcile_size()had nothing to reconcile and the path was hit once, not twelve times. The 2D/3D view-count switch alone (submit=1-viewvssubmit=2-view, same 1468x748) does not trigger a bridge reallocation.Not this bug — split out
Crash_2026-09-01_0244GetRenderingResolutionunderDeviceInfoEvent::CollectExtraInfounderMainMessageLoop. 13 flat frames, no mono, no recursion; zerostack overflow/recursionhits in the whole log.LeiaViewer.35556CLibrary::Serialize.Crash_2026-08-31_065640000015inAssetImportWorker6— a different process; likely a fourth thing. Log pull pending.Note for #282: the render-target layer is not ruled out there. It dies reading rendering resolution on a box where a DisplayXR session had been changing the render target. That is an observation, not a mechanism.
Next — in value order
Unity.exe.23896. Decides managed-vs-native recursion outright and ends the guessing.GetWindowLongPtrW(hwnd, GWLP_WNDPROC)on the editor's main window afterLifecycle Shutdown, mapped to a module. If it lands in an SR module, the stale-subclass mechanism is confirmed. One call, non-invasive.DisplayXRClient.dll) still mapped post-shutdown? If the subclass survives but the code does not, that is a dangling wndproc and the next message is fatal, not the 2500th._handlepath apply PR #1012's destroy-before-recreate discipline?Related:
displayxr-leia-plugin#217(the neighbouring unbounded-burst string,Weaving is not possible because window handle is invalid).