Avalonia
Avalonia copied to clipboard
Crash when running on Windows 11 on ARM
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
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()
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)
to add to that, now that Rider has made its first appearance on arm64/Windows it reports System.Security.VerificationException
here
![image](https://user-images.githubusercontent.com/323250/199218322-982bddf6-9a52-4b56-9fdf-d8f9e26aa34e.png)
@olifink great findings. Are you able to submit a PR with a fix for it?
@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.
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 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.
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.
@Lakritzator if you can test this branch or build on your device, please do https://github.com/AvaloniaUI/Avalonia/pull/9342
@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
@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.
@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 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 locationBad 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.
@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 yes, I am building and running on 7.0.0-rc.2.22472.3 - that's where no content is shown
@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)
@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)
Try disabling GPU rendering and other thing to try Direct2D1 backend