Skip to content

CompositionTarget::GetCompositorForCurrentThread: don't originate an error during core shutdown - #11731

Open
Abhijeet Jha (iamAbhi-916) wants to merge 1 commit into
mainfrom
user/abhijeetjha/compositiontarget-shutdown-failfast
Open

CompositionTarget::GetCompositorForCurrentThread: don't originate an error during core shutdown#11731
Abhijeet Jha (iamAbhi-916) wants to merge 1 commit into
mainfrom
user/abhijeetjha/compositiontarget-shutdown-failfast

Conversation

@iamAbhi-916

@iamAbhi-916 Abhijeet Jha (iamAbhi-916) commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Description:
An app that enables DebugSettings.FailFastOnErrors and uses AcrylicBrush fail-fasts with 0xC000027B during normal shutdown. Dev Home hits this on every exit.

The stowed exception is hr=8001010E (RPC_E_WRONG_THREAD) originated at CompositionTarget.cpp:227, in the destructor of a brush that XAML is itself tearing down.

Root cause:
DXamlCore::DeinitializeInstance sets m_state = Deinitializing (DXamlCore.cpp:1026) and then runs CommonShutdown -> ShutdownAllPeers, which releases peers and destroys the brush.

SHUTDOWN - DXamlCore::DeinitializeInstance, m_state = Deinitializing

  DXamlCore::CommonShutdown                         dxaml/lib/DXamlCore.cpp:1052
  +- DXamlCore::ShutdownAllPeers                    dxaml/lib/DXamlCore.cpp:1873
       +- DependencyObject::EndShutdown -> DisconnectFrameworkPeer -> ClearPeerReferences
            +- AcrylicBrush::~AcrylicBrush          controls/dev/Materials/Acrylic/AcrylicBrush.cpp:26
                 +- MaterialHelper::NoiseChanged    controls/dev/Lights/MaterialHelper.cpp:265
                      +- LifetimeHandler::TryGetMaterialHelperInstance
                      |    controls/dev/Common/LifetimeHandler.cpp:106
                      |    auto ignorehr = ...GetCompositorForCurrentThread(...)   <- result ignored by design
                      |
                      +- CompositionTarget::GetCompositorForCurrentThread
                           dxaml/lib/CompositionTarget.cpp:227
                           IFC_RETURN(CheckActivationAllowed())                    <- returns RPC_E_WRONG_THREAD
                                                                                     and originates it

       IFC_RETURN -> error context stowed
         ShouldFailFastOnStowedException            components/base/errorcontext.cpp:1169
         g_failFastOnErrors set via DebugSettings   dxaml/lib/DebugSettings_Partial.cpp:72
         -> FAIL_FAST_USING_EXISTING_ERROR_CONTEXT, 0xC000027B

The HRESULT is correct and the caller already handles it. The defect is that an expected teardown condition is originated as a failure, and FailFastOnErrors cannot tell the two apart.

Fix:
Return the HRESULT without originating it when this thread's core is shutting down.

Behavior:
Callers on a live core are unaffected and still get a Compositor.

A query during core shutdown returns RPC_E_WRONG_THREAD to the caller exactly as before, and no longer originates an error context, so FailFastOnErrors does not fire.

A query from a thread that has no core still fails fast.

Testing:
Repro'd locally in a WinUI 3 app, merge base against the fix, one process per case, swapping only Microsoft.ui.xaml.dll (amd64chk).

Acrylic has to actually render for the bug to arm: MaterialHelper::m_acrylicCompositor is only set in AssertUniqueCompositorOrUpdate, which the solid-colour fallback path never reaches, so the repro forces the real acrylic path through MaterialHelperTestApi.IgnoreAreEffectsFast and exits with the brush still in the live tree.

case merge base fix
AcrylicBrush released by ShutdownAllPeers, FailFastOnErrors on 0xC000027B 0
same, FailFastOnErrors off 0 0
GetCompositorForCurrentThread on a thread with no core 0xC000027B 0xC000027B
GetCompositorForCurrentThread on the UI thread, live core 0 (Compositor) 0 (Compositor)
GetCompositorForCurrentThread after the core is deleted 0xC000027B 0xC000027B

Exactly one cell changes. Row 2 confirms the crash requires the FailFastOnErrors opt-in, rows 3 and 5 confirm the diagnostic is preserved outside the shutdown window.

…error during core shutdown

Cleanup running through DXamlCore::ShutdownAllPeers can query the compositor and
handles the failure itself. Originating the expected RPC_E_WRONG_THREAD there makes
FailFastOnErrors terminate the process during normal shutdown.
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@microsoft-github-policy-service microsoft-github-policy-service Bot added the needs-triage Issue needs to be triaged by the area owners label Aug 31, 2026
@iamAbhi-916
Abhijeet Jha (iamAbhi-916) marked this pull request as ready for review August 31, 2026 15:37
@iamAbhi-916
Abhijeet Jha (iamAbhi-916) requested a review from a team as a code owner August 31, 2026 15:37
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@iamAbhi-916

Copy link
Copy Markdown
Contributor Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
1 pipeline(s) were filtered out due to trigger conditions.

@iamAbhi-916 Abhijeet Jha (iamAbhi-916) removed the needs-triage Issue needs to be triaged by the area owners label Sep 1, 2026
// and handles the failure itself, so don't originate an error for it.
if (pdxc && DXamlCore::IsShuttingDownStatic())
{
return CheckActivationAllowed();

@godlytalias Godly T.Alias (godlytalias) Sep 1, 2026

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.

Dropping IFC_RETURN will just avoid storing stowed exception which in turn may impact debugging as we won't be having a stowed exception captured in case of a real failure


// Cleanup running during core shutdown through ShutdownAllPeers() can query the compositor
// and handles the failure itself, so don't originate an error for it.
if (pdxc && DXamlCore::IsShuttingDownStatic())

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.

Can't we avoid calling this if shutting down?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants