Skip to content

Guard island input site lookup during shutdown - #11654

Open
Essam (TheBlueSky) wants to merge 1 commit into
microsoft:mainfrom
TheBlueSky:fix/island-input-site-null-during-shutdown
Open

Guard island input site lookup during shutdown#11654
Essam (TheBlueSky) wants to merge 1 commit into
microsoft:mainfrom
TheBlueSky:fix/island-input-site-null-during-shutdown

Conversation

@TheBlueSky

Copy link
Copy Markdown

Fixes

Fixes #11653

PR Type

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no API changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

Description

Carries forward Jon Wiswall (@jonwis)'s fix from #11063, rebased onto the current dxaml/ layout (that PR still patches the old src/dxaml/... path, so it no longer applies). Credit for the diagnosis and the fix is his — I hit the same crash independently and he suggested opening a fresh issue and PR to move it to completion.

CDependencyObject::GetElementIslandInputSite() dereferenced the result of CCoreServices::GetInputServices() without a null check:

return coreServices->GetInputServices()->GetPrimaryRegisteredIslandInputSite();

During framework shutdown the input services are already gone, so this runs GetPrimaryRegisteredIslandInputSite() on a null this and faults while reading m_islandInputSiteRegistrations. Tearing down a focused TextBox reaches it via CTextBoxBase::Destroy → the RichEdit gripper code → TextServicesHost::TxGetWindow.

This PR null-checks core services and input services and returns nullptr instead. It also adds the matching coreServices && guard on the HasXamlIslandRoots() call above, as in the original PR.

Returning null is safe because it is already the contract: every caller of GetElementIslandInputSite() funnels the result into CInputServices::GetUnderlyingInputHwndFromIslandInputSite(), which is declared _In_opt_ and null-checks its argument before use. GetPrimaryRegisteredIslandInputSite() itself already returns nullptr when no island input sites are registered, so callers must handle null regardless.

Current Behavior

Closing a window while a TextBox has focus crashes the process with 0xC0000005 inside Microsoft.UI.Xaml.dll during shutdown. Reproduces 3/3 on 1.7.260224002, 1.8.260317003, 1.8.260804001 and 2.4.0 (details and a minimal repro in the linked issue).

New Behavior

The lookup returns nullptr when there is no input site left to return, callers treat that as "no input hwnd" as they already do, and the app exits cleanly with exit code 0.

Customer Impact

User-facing. Any app that leaves a text input focused when the window closes currently dies with an access violation instead of exiting cleanly. It is invisible to the user mid-session but logs an Application Error / WER crash on every exit, drowning real crashes in telemetry and breaking any work that depends on a clean shutdown.

Regression Potential

  • Low risk — isolated change, limited scope
  • Medium risk — touches shared components or public APIs
  • High risk — architectural or breaking API change

The change only alters behaviour on paths that dereference a null pointer today, i.e. paths that currently crash. When core services and input services are alive the behaviour is byte-for-byte identical.

One caveat carried over from #11063: Jon Wiswall (@jonwis) noted that all callsites handle a null return except DirectManipulation. The DManip path goes through CInputServices::GetIslandInputSiteRegistrationForUIElement(), which FAIL_FAST_IFs on a missing registration but does not call GetElementIslandInputSite(), so it is not reached by this change. Worth a second pair of eyes from someone who owns that area.

Testing

I tried to validate this with a local build and could not get there. init.cmd amd64chk completes fine, but build.cmd mux /i amd64chk fails in XamlCompilerPrerequisites.sln with MSB8040 — Spectre-mitigated libraries are required — for manifest.vcxproj, gencompheadersandidl.vcxproj and genmrtheadersandidl.vcxproj. Neither toolset on this machine ships them (VS 2022 14.44 or VS 2026 14.51), and setting SpectreMitigation=false in the environment does not override it for those three projects even though eng/common.props guards the property. Two notes in passing, in case they are useful: the build selected the VS 2026 MSBuild while OneTimeSetup.cmd is documented as assuming VS 2022, and GettingStarted.md says CI builds are not supported yet, so I do not know whether this PR gets an automated build.

So to be clear about what is and is not verified: the change is a null check applied to the current source and checked by reading every caller, not by compiling. Happy to install the .vsconfig components and retry if you would like a local build result before this merges.

Verified against shipped binaries that the bug is still live and that the behaviour is exactly what the guard addresses:

Scenario (Windows App SDK 2.4.0) Result
Repro app, TextBox focused at close 3/3 crash, 0xC0000005
Repro app, TextBox never focused 3/3 clean exit (0)
Repro app, focus moved off the input in AppWindow.Closing 3/3 clean exit (0)

CDependencyObject::GetElementIslandInputSite() called
CCoreServices::GetInputServices()->GetPrimaryRegisteredIslandInputSite()
without checking the result of GetInputServices(). By the time a focused
TextBox is torn down during framework shutdown the input services are
already gone, so the call runs on a null "this" and faults while reading
m_islandInputSiteRegistrations.

Null-check core services and input services and return nullptr instead.
Every caller already funnels the result through
CInputServices::GetUnderlyingInputHwndFromIslandInputSite(), which is
declared _In_opt_ and null-checks its argument, so "no island input site"
is already an expected result.

Carries forward the fix proposed by @jonwis in microsoft#11063, rebased onto the
current dxaml/ layout.
@TheBlueSky
Essam (TheBlueSky) requested a review from a team as a code owner August 26, 2026 06:32
@microsoft-github-policy-service microsoft-github-policy-service Bot added the needs-triage Issue needs to be triaged by the area owners label Aug 26, 2026
@TheBlueSky

Copy link
Copy Markdown
Author

Some context on where this came from, since I don't want to take more credit than I'm due.

I hit this crash while working on my own app. The digging that followed — narrowing it down to a focused text input at teardown, building the minimal repro, re-testing it across 1.7 through 2.4.0, and reading through the callers to check that a null return is actually safe — was done with a lot of help from coding agents. The write-up in #11653 and the verification tables here are mostly the product of that, not of me reading the XAML core by hand.

The fix itself is Jon's, from #11063. I rebased it onto the current layout and wrote it up, but I didn't come up with it.

So this is his fix, my app's crash and repro, and a fair amount of agent-assisted legwork — rather than my work alone. Flagging it so nobody reviews it under the wrong assumption about where the confidence in it comes from.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A fix was done for the same issue, 691c6a7

Please check whether the crash gets fixed with the same

cc: Abhijeet Jha (@iamAbhi-916)

@JesseCol

Copy link
Copy Markdown

A fix was done for the same issue, 691c6a7

Please check whether the crash gets fixed with the same

cc: Abhijeet Jha (Abhijeet Jha (@iamAbhi-916))

If these changes both had test coverage, we'd know right away. Is it possible to add a test for this?

@TheBlueSky

Copy link
Copy Markdown
Author

Godly T.Alias (@godlytalias) thanks for digging that one up, I hadn't found it.

I tested against the newest bits I could get from NuGet, including 2.4.1-experimental, and the crash still reproduces there. So it may be that the commit hasn't made it into anything published yet.

If you can point me at a build that definitely contains it, I'll happily test against that and report back here.

@TheBlueSky

Copy link
Copy Markdown
Author

Jesse Collins (@JesseCol) agreed, test coverage would settle this straight away rather than us comparing two fixes by hand.

Let me have a look at what's possible there and come back to you.

@iamAbhi-916

Copy link
Copy Markdown
Contributor

Jesse Collins (Jesse Collins (@JesseCol)) agreed, test coverage would settle this straight away rather than us comparing two fixes by hand.

Let me have a look at what's possible there and come back to you.

essam Jesse Collins (@JesseCol) yeah, the fix was not serviced in any of the recent updates of winappsdk.

I am trying to repro the same issue locally from main (which contains the prior fix I did). Will keep you guys posted on the same by EOD, if the prior fix already has the issue mitigated, I will add a test for it to confirm and close this.

Meanwhile I will also service it for September release.

@iamAbhi-916

Abhijeet Jha (iamAbhi-916) commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Some context on where this came from, since I don't want to take more credit than I'm due.

I hit this crash while working on my own app. The digging that followed — narrowing it down to a focused text input at teardown, building the minimal repro, re-testing it across 1.7 through 2.4.0, and reading through the callers to check that a null return is actually safe — was done with a lot of help from coding agents. The write-up in #11653 and the verification tables here are mostly the product of that, not of me reading the XAML core by hand.

The fix itself is Jon's, from #11063. I rebased it onto the current layout and wrote it up, but I didn't come up with it.

So this is his fix, my app's crash and repro, and a fair amount of agent-assisted legwork — rather than my work alone. Flagging it so nobody reviews it under the wrong assumption about where the confidence in it comes from.

Also thanks Essam (@TheBlueSky) for taking the time and initiative to file the issue and contribute for the fix, much appreciated!

@iamAbhi-916

Abhijeet Jha (iamAbhi-916) commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Jesse Collins (Jesse Collins (@JesseCol)) agreed, test coverage would settle this straight away rather than us comparing two fixes by hand.

Let me have a look at what's possible there and come back to you.

Repro'd: Closing the window with a TextBox focused AV 0xC0000005 in CInputServices::GetPrimaryRegisteredIslandInputSite during shutdown

Issue is already fixed with 691c6a7 on main .

Without the above fix CCoreServices::~CCoreServices was nulling m_inputServices before delete m_pTextCore.
Text-core teardown then re-enters input via OnTxInPlaceDeactivate -> TxGetWindow -> GetElementIslandInputSite and reads m_islandInputSiteRegistrations off a null CInputServices.

with the fix (moving the reset to after the text core is torn down) we dont see it main.

Essam (@TheBlueSky) I will service the fix in next servicing release (ETA September end) and will also add a test for this scenario in main, your diagnosis was on point, and the repro was genuinely useful in confirming the servicing gap.

fyr Jesse Collins (@JesseCol) Godly T.Alias (@godlytalias)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-triage Issue needs to be triaged by the area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash on shutdown (0xC0000005) tearing down a focused TextBox: GetElementIslandInputSite dereferences null input services

4 participants