Avalonia icon indicating copy to clipboard operation
Avalonia copied to clipboard

Crash when running on Windows 11 on ARM

Open wieslawsoltes opened this issue 1 year ago • 5 comments

Describe the bug

An unhandled exception of type 'System.AccessViolationException' occurred in Avalonia.Win32.dll Attempted to read or write protected memory. This is often an indication that other memory is corrupt

To Reproduce

Run new Avalonia app from template on Windows 11 on ARM

Expected behavior

No crash

Screenshots

image

Desktop (please complete the following information):

  • OS: Windows 11 on ARM
  • Version 0.10.x

Additional context

Running inside VM MacOS M1 Parallels

Disabling WindowsUIComposition avoids crash.

new Win32PlatformOptions() {  UseWindowsUIComposition = false }

https://github.com/AvaloniaUI/Avalonia/blob/1eead138fc649dcc2a2bd77148e91b2ea01f2b4f/src/Windows/Avalonia.Win32/WinRT/winrt.idl#L445-L446

https://github.com/dotnet/runtime/issues/72321

[External Code] 
> dcomp.dll!Microsoft::WRL::Details::DelegateArgTraits<long (__cdecl Windows::Foundation::IAsyncActionCompletedHandler::*)(Windows::Foundation::IAsyncAction *,enum ABI::Windows::Foundation::AsyncStatus)>::DelegateInvokeHelper<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<2>,Windows::Foundation::IAsyncActionCompletedHandler,Microsoft::WRL::FtmBase>,<lambda_2a41ea20f21462c29868894764bbafd5>,-1,Windows::Foundation::IAsyncAction *,enum ABI::Windows::Foundation::AsyncStatus>::Invoke() Unknown
  dcomp.dll!Microsoft::WRL::InvokeTraits<-2>::InvokeDelegates<<lambda_235ffb6b1ffc6a4928642e92ab1f25a5>,Windows::Foundation::IAsyncActionCompletedHandler>() Unknown
  dcomp.dll!<lambda>(void)() Unknown
  dcomp.dll!Microsoft::WRL2::ContextSession::LeaveSession_Callback<<lambda>(void)>() Unknown
  dcomp.dll!Windows::UI::Composition::CompositorCommon::OnCommitCompletion(void) Unknown
  CoreMessaging.dll!CFlat::SehSafe::Execute<<lambda_19cca5ef35227df66cdfebe4b6644b4b>>() Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::WaitCallback::ImportAdapter$() Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::RegisteredWait::DoCallback() Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::DeferredCall::Callback_Dispatch() Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::DeferredCallDispatcher::Callback_OnDispatch() Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::EventLoop::Callback_RunCoreLoop() Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DrainCoreMessagingQueue(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *) Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatch(bool,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *) Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatchRaw(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool,void * *) Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DoWork(struct HWND__ *,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool) Unknown
  CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::WindowProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
  user32.dll!UserCallWinProcCheckWow(struct _ACTIVATION_CONTEXT *,__int64 (*)(struct tagWND *,unsigned int,unsigned int64,__int64),struct HWND *,enum _WM_VALUE,unsigned __int64,__int64,void *,int) Unknown
  user32.dll!DispatchClientMessage() Unknown
  user32.dll!__fnDWORD () Unknown
  ntdll.dll!KiUserCallbackDispatcherReturn () Unknown
  win32u.dll!NtUserGetMessage () Unknown
  user32.dll!GetMessageW() Unknown
  [External Code] 
  kernel32.dll!BaseThreadInitThunk() Unknown
  ntdll.dll!RtlUserThreadStart() Unknown
[Managed to Native Transition]
Avalonia.Win32.dll!Avalonia.Win32.WinRT.Impl.__MicroComICompositionGraphicsDeviceProxy.CreateDrawingSurface(Avalonia.Win32.Interop.UnmanagedMethods.SIZE sizePixels, Avalonia.Win32.WinRT.DirectXPixelFormat pixelFormat, Avalonia.Win32.WinRT.DirectXAlphaMode alphaMode)
Avalonia.Win32.dll!Avalonia.Win32.WinRT.Composition.WinUICompositorConnection.CreateWindow(nint hWnd)
Avalonia.Win32.dll!Avalonia.Win32.WinRT.Composition.WinUiCompositedWindowSurface.CreateGlRenderTarget()
Avalonia.Skia.dll!Avalonia.Skia.GlRenderTarget.GlRenderTarget(SkiaSharp.GRContext grContext, Avalonia.OpenGL.Surfaces.IGlPlatformSurface glSurface)
Avalonia.Skia.dll!Avalonia.Skia.GlSkiaGpu.TryCreateRenderTarget(System.Collections.Generic.IEnumerable<object> surfaces)
Avalonia.Skia.dll!Avalonia.Skia.PlatformRenderInterface.CreateRenderTarget(System.Collections.Generic.IEnumerable<object> surfaces)
Avalonia.Controls.dll!Avalonia.Controls.TopLevel.CreateRenderTarget()
Avalonia.Controls.dll!Avalonia.Controls.TopLevel.Avalonia.Rendering.IRenderRoot.CreateRenderTarget()
Avalonia.Base.dll!Avalonia.Rendering.Composition.Server.ServerCompositionTarget.Render()
Avalonia.Base.dll!Avalonia.Rendering.Composition.Server.ServerCompositor.RenderCore()
Avalonia.Base.dll!Avalonia.Rendering.Composition.Server.ServerCompositor.Render()
Avalonia.Base.dll!Avalonia.Rendering.RenderLoop.TimerTick(System.TimeSpan time)
Avalonia.Win32.dll!Avalonia.Win32.WinRT.Composition.WinUICompositorConnection.RunLoopHandler.Invoke(Avalonia.Win32.WinRT.IAsyncAction asyncInfo, Avalonia.Win32.WinRT.AsyncStatus asyncStatus)
Avalonia.Win32.dll!Avalonia.Win32.WinRT.Impl.__MicroComIAsyncActionCompletedHandlerVTable.Invoke(void* this, void* asyncInfo, Avalonia.Win32.WinRT.AsyncStatus asyncStatus)
[Native to Managed Transition]
dcomp.dll!Microsoft::WRL::Details::DelegateArgTraits<long (__cdecl Windows::Foundation::IAsyncActionCompletedHandler::*)(Windows::Foundation::IAsyncAction *,enum ABI::Windows::Foundation::AsyncStatus)>::DelegateInvokeHelper<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<2>,Windows::Foundation::IAsyncActionCompletedHandler,Microsoft::WRL::FtmBase>,<lambda_2a41ea20f21462c29868894764bbafd5>,-1,Windows::Foundation::IAsyncAction *,enum ABI::Windows::Foundation::AsyncStatus>::Invoke()
dcomp.dll!Microsoft::WRL::InvokeTraits<-2>::InvokeDelegates<<lambda_235ffb6b1ffc6a4928642e92ab1f25a5>,Windows::Foundation::IAsyncActionCompletedHandler>()
dcomp.dll!<lambda>(void)()
dcomp.dll!Microsoft::WRL2::ContextSession::LeaveSession_Callback<<lambda>(void)>()
dcomp.dll!Windows::UI::Composition::CompositorCommon::OnCommitCompletion(void)
CoreMessaging.dll!CFlat::SehSafe::Execute<<lambda_19cca5ef35227df66cdfebe4b6644b4b>>()
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::WaitCallback::ImportAdapter$()
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::RegisteredWait::DoCallback()
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::DeferredCall::Callback_Dispatch()
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::DeferredCallDispatcher::Callback_OnDispatch()
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::EventLoop::Callback_RunCoreLoop()
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DrainCoreMessagingQueue(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *)
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatch(bool,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *)
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatchRaw(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool,void * *)
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DoWork(struct HWND__ *,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool)
CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::WindowProc(struct HWND__ *,unsigned int,unsigned __int64,__int64)
user32.dll!UserCallWinProcCheckWow(struct _ACTIVATION_CONTEXT *,__int64 (*)(struct tagWND *,unsigned int,unsigned int64,__int64),struct HWND *,enum _WM_VALUE,unsigned __int64,__int64,void *,int)
user32.dll!DispatchClientMessage()
user32.dll!__fnDWORD ()
ntdll.dll!KiUserCallbackDispatcherReturn ()
win32u.dll!NtUserGetMessage ()
user32.dll!GetMessageW()
[Managed to Native Transition]
Avalonia.Win32.dll!Avalonia.Win32.WinRT.Composition.WinUICompositorConnection.RunLoop()
Avalonia.Win32.dll!Avalonia.Win32.WinRT.Composition.WinUICompositorConnection.TryCreateAndRegisterCore.AnonymousMethod__0()
[Native to Managed Transition]
kernel32.dll!BaseThreadInitThunk()
ntdll.dll!RtlUserThreadStart()

wieslawsoltes avatar Aug 18 '22 11:08 wieslawsoltes

same behavior on Windows on Arm/Project Voltera/Windows DevKit 2023 machine. Exception in Avalonia.Win32.dll 0.10.18.0 at

Avalonia.Win32.WinRT.Impl.__MicroComICompositionGraphicsDeviceProxy.CreateDrawingSurface(Avalonia.Win32.Interop.UnmanagedMethods.SIZE, Avalonia.Win32.WinRT.DirectXPixelFormat, Avalonia.Win32.WinRT.DirectXAlphaMode)

olifink avatar Nov 01 '22 10:11 olifink

to add to that, now that Rider has made its first appearance on arm64/Windows it reports System.Security.VerificationException here

image

olifink avatar Nov 01 '22 10:11 olifink

@olifink great findings. Are you able to submit a PR with a fix for it?

timunie avatar Nov 02 '22 05:11 timunie

@timunie I'd be happy to help but I have no idea what needs to be done to fix this. I've just shared any insights I found.

olifink avatar Nov 02 '22 08:11 olifink

for what it's worth, I've checked out the repo to see if I can find out more what's happening. The exception is thrown from code that appears to be generated at build time from winrt.idl - specifically this method:

interface ICompositionGraphicsDevice : IInspectable
{
    HRESULT CreateDrawingSurface([in] SIZE sizePixels, ...

now SIZE here is defined in UnmanagedMethods.cs as a struct of two ìnt` which are passed as 0,0 (which appears to be ok)

however the Size datatype used by CreateDrawingSurface are defined as floats. So possibly arm64 is more stringent as to the type or marshalls memory differently, because it reports Attempted to read or write protected memory in the exception, and float are larger than int - which could explain this.

there also appears to exist a CreateDrawingSurface2 which indeed does differ in defining the sizePixel parameter type as SizeInt32, maybe that could be used.

but, I have no idea how Avalonia actually is intended to work here...

olifink avatar Nov 02 '22 11:11 olifink

@olifink unfortunately I don't think anybody in the core team has Windows ARM right now. But I can help you with MicroCOM related changes, if you have time to try possible fixes you mentioned above.

You can create another SIZE structure with floats in it defined in the same class, let's say SIZE_F. Then all you need is to update COM interface method declaration:

HRESULT CreateDrawingSurface([in] SIZE_F sizePixels

And in the beginning of winrt.idl file you will need to define mapping for this struct:

@clr-map SIZE_F Avalonia.Win32.Interop.UnmanagedMethods.SIZE_F

After you build a project, generated code will use a new struct in this method. Most likely you will need to update usage of this method to use a correct struct as well, there will be helpful compile errors.

maxkatz6 avatar Nov 02 '22 18:11 maxkatz6

About CreateDrawingSurface2, it seems it can be used, yes. It was added later in another SDK update (10.0.15063.0). But Avalonia uses these APIs only on even newer Windows builds (I think 10.0.17xxx and newer, don't remember exactly). So it's safe to use that.

To do so, I found IDL definition for this interface: https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.16299.0/winrt/windows.ui.composition.idl#L1016

Slightly adapted it to the MicroCOM IDL syntax:

[uuid(0FB8BDF6-C0F0-4BCC-9FB8-084982490D7D)]
interface ICompositionGraphicsDevice2 : IInspectable
{
    HRESULT CreateDrawingSurface2([in] SIZE sizePixels, [in] DirectXPixelFormat pixelFormat, [in] DirectXAlphaMode alphaMode, [out] [retval] ICompositionDrawingSurface** result);
}

And replaced old call with a new one:

using var device2 = _device.QueryInterface<ICompositionGraphicsDevice2>();

using var drawingSurface = device2.CreateDrawingSurface2(new UnmanagedMethods.SIZE(), DirectXPixelFormat.B8G8R8A8UIntNormalized,
    DirectXAlphaMode.Premultiplied);

Seems to work fine on my x64 machine with this new method. I wonder if it solves it for ARM.

maxkatz6 avatar Nov 02 '22 18:11 maxkatz6

@Lakritzator if you can test this branch or build on your device, please do https://github.com/AvaloniaUI/Avalonia/pull/9342

maxkatz6 avatar Nov 02 '22 18:11 maxkatz6

@maxkatz6 just to be clear, I unfortunately do not have an ARM device. I tried to build the branch, but after getting into all kinds of activities like downgrading workloads etc, I quit after an hour. Also needing .NET Core 2.1 with all the reported CVEs (e.g. CVE-2021-24112) made me second guess. So I didn't manage to test anything, sorry

Lakritzator avatar Nov 03 '22 07:11 Lakritzator

@maxkatz6 that was quick, I was about to do the changes today. So, I have rebuilt from master with your changes and have good news and bad news:

Good it fixes the crash memory corruption with CreateDrawingSurface2 and no exception occurs at that location

Bad in that doesn't mean it's working yet: there are no exceptions but we end up with an empty window frame and it doesn't appear that whatever gets painted on the drawing surface is moved back into the window.

Could be similar cause that's just not hitting a memory exception, I see if I can narrow it down a bit more.

olifink avatar Nov 03 '22 10:11 olifink

@Lakritzator my apologies, I pinged a wrong person.

@olifink thank you testing these changes. If you will find anything else, please let me know.

maxkatz6 avatar Nov 03 '22 18:11 maxkatz6

@maxkatz6 that was quick, I was about to do the changes today. So, I have rebuilt from master with your changes and have good news and bad news:

Good it fixes the crash memory corruption with CreateDrawingSurface2 and no exception occurs at that location

Bad in that doesn't mean it's working yet: there are no exceptions but we end up with an empty window frame and it doesn't appear that whatever gets painted on the drawing surface is moved back into the window.

Could be similar cause that's just not hitting a memory exception, I see if I can narrow it down a bit more.

Did you try running using .NET 7 RC2 ARM64 SDK ? I had run successfully app on that SDK without issues.

wieslawsoltes avatar Nov 03 '22 21:11 wieslawsoltes

@maxkatz6 that was quick, I was about to do the changes today. So, I have rebuilt from master with your changes and have good news and bad news: Good it fixes the crash memory corruption with CreateDrawingSurface2 and no exception occurs at that location Bad in that doesn't mean it's working yet: there are no exceptions but we end up with an empty window frame and it doesn't appear that whatever gets painted on the drawing surface is moved back into the window. Could be similar cause that's just not hitting a memory exception, I see if I can narrow it down a bit more.

Did you try running using .NET 7 RC2 ARM64 SDK ? I had run successfully app on that SDK without issues.

image

wieslawsoltes avatar Nov 03 '22 22:11 wieslawsoltes

@wieslawsoltes yes, I am building and running on 7.0.0-rc.2.22472.3 - that's where no content is shown

olifink avatar Nov 05 '22 12:11 olifink

@wieslawsoltes same results with the final release of net 7.0 - empty window on a real Windows Arm machine. It seems very likely that mac Parallels replaces/redirects the display driver/compositor to macOS native/metal, so the behavior in rendering is different on Windows Arm hardware than on emulation

Also, when I try the original workaround you described with UseWindowsUIComposition = false I get a completely black window, same as any other Avalonia based app I try to run (Lunacy, dotMemory, dotTrace)

image

olifink avatar Nov 09 '22 15:11 olifink

@wieslawsoltes same results with the final release of net 7.0 - empty window on a real Windows Arm machine. It seems very likely that mac Parallels replaces/redirects the display driver/compositor to macOS native/metal, so the behavior in rendering is different on Windows Arm hardware than on emulation

Also, when I try the original workaround you described with UseWindowsUIComposition = false I get a completely black window, same as any other Avalonia based app I try to run (Lunacy, dotMemory, dotTrace)

image

Try disabling GPU rendering and other thing to try Direct2D1 backend

wieslawsoltes avatar Nov 09 '22 16:11 wieslawsoltes