marzent / IINACT

A Dalamud plugin to run the FFXIV_ACT_Plugin in an ACT-like enviroment with a heavily modified port of Overlay Plugin
https://www.iinact.com
GNU General Public License v3.0
182 stars 41 forks source link

1.0 .NET 7 build fails to launch under Wine #29

Closed joshua-software-dev closed 1 year ago

joshua-software-dev commented 1 year ago

Tested on latest Arch Linux.

with XIV Core Wine WINEPREFIX=~/.xlcore/wineprefix WINEESYNC=1 DOTNET_BUNDLE_EXTRACT_BASE_DIR="C:\\IINACT\\" ~/.xlcore/compatibilitytool/beta/wine-xiv-staging-fsync-git-7.10.r3.g560db77d/bin/wine64 "$HOME/.xlcore/wineprefix/drive_c/IINACT/IINACT.exe"

esync: up and running.
002c:fixme:winediag:LdrInitializeThunk Wine XIV (staging) 7.10 is a testing version containing experimental patches.
002c:fixme:winediag:LdrInitializeThunk Please don't report bugs about it on winehq.org and use https://github.com/goatcorp/wine-xiv-git/issues instead.
wine: configuration in L"/home/jfield/.xlcore/wineprefix" has been updated.
0138:fixme:heap:GetNumaHighestNodeNumber semi-stub: 000000000019EFDC
0138:fixme:process:GetProcessGroupAffinity (FFFFFFFFFFFFFFFF,000000000019EF64,0000000000000000): stub
0138:fixme:seh:WerRegisterRuntimeExceptionModule (L"C:\\IINACT\\mscordaccore.dll", 0000000140000000) stub
0138:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
Failed to create CoreCLR, HRESULT: 0x80004005
0138:fixme:advapi:RegisterEventSourceW ((null),L".NET Runtime"): stub
0138:fixme:advapi:ReportEventW (00000000CAFE4242,0x0001,0x0000,0x000003ff,0000000000000000,0x0001,0x00000000,000000000019FCA0,0000000000000000): stub
0138:err:eventlog:ReportEventW L"Description: A .NET application failed.\nApplication: IINACT.exe\nPath: C:\\IINACT\\IINACT.exe\nMessage: Failed to create CoreCLR, HRESULT: 0x80004005\n\n"
0138:fixme:advapi:DeregisterEventSource (00000000CAFE4242) stub

with system wine: WINEPREFIX=~/.xlcore/wineprefix WINEESYNC=1 DOTNET_BUNDLE_EXTRACT_BASE_DIR="C:\\IINACT\\" wine "$HOME/.xlcore/wineprefix/drive_c/IINACT/IINACT.exe"

0084:fixme:hid:handle_IRP_MN_QUERY_ID Unhandled type 00000005
0084:fixme:hid:handle_IRP_MN_QUERY_ID Unhandled type 00000005
0084:fixme:hid:handle_IRP_MN_QUERY_ID Unhandled type 00000005
0084:fixme:hid:handle_IRP_MN_QUERY_ID Unhandled type 00000005
010c:fixme:heap:GetNumaHighestNodeNumber semi-stub: 000000000019EFDC
010c:fixme:process:GetProcessGroupAffinity (FFFFFFFFFFFFFFFF,000000000019EF64,0000000000000000): stub
010c:fixme:seh:WerRegisterRuntimeExceptionModule (L"C:\\IINACT\\mscordaccore.dll", 0000000140000000) stub
010c:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
Failed to create CoreCLR, HRESULT: 0x80004005
010c:fixme:advapi:RegisterEventSourceW ((null),L".NET Runtime"): stub
010c:fixme:advapi:ReportEventW (00000000CAFE4242,0x0001,0x0000,0x000003ff,0000000000000000,0x0001,0x00000000,000000000019FCA0,0000000000000000): stub
010c:err:eventlog:ReportEventW L"Description: A .NET application failed.\nApplication: IINACT.exe\nPath: C:\\IINACT\\IINACT.exe\nMessage: Failed to create CoreCLR, HRESULT: 0x80004005\n\n"
010c:fixme:advapi:DeregisterEventSource (00000000CAFE4242) stub

I also cloned the repo and set all the csproj's to net6-windows from net7-windows (as well as patching various files in FFXIVClientStructs to not use .NET 7isms) and everything worked fine. I'm able to parse in game successfully with my manually built version. I'm thinking its somehow related to .NET 7 because of this, as from searching the error is seems to be an extremely early load failure for .NET, such that it might even be difficult to do debugging as the CLR hasn't setup any of the debugging utils as early as this fails. The command I used to compile to .NET 6 version for info: dotnet publish --self-contained true -c release --maxcpucount:1 -p:EnableWindowsTargeting=true

joshua-software-dev commented 1 year ago

Upon further testing, this may just be a every .NET 7 program under wine problem. Running a brand new, dotnet new console hello world, self contained, single file project under wine:

~/.xlcore/compatibilitytool/beta/wine-xiv-staging-fsync-git-7.10.r3.g560db77d/bin/wine64 helloworld.exe

wineserver: using server-side synchronization.
002c:fixme:winediag:LdrInitializeThunk Wine XIV (staging) 7.10 is a testing version containing experimental patches.
002c:fixme:winediag:LdrInitializeThunk Please don't report bugs about it on winehq.org and use https://github.com/goatcorp/wine-xiv-git/issues instead.
0100:fixme:heap:GetNumaHighestNodeNumber semi-stub: 000000000019EFDC
0100:fixme:process:GetProcessGroupAffinity (FFFFFFFFFFFFFFFF,000000000019EF64,0000000000000000): stub
0100:fixme:seh:WerRegisterRuntimeExceptionModule (L"C:\\IINACT\\mscordaccore.dll", 0000000140000000) stub
0100:fixme:ntdll:NtQuerySystemInformation info_class SYSTEM_PERFORMANCE_INFORMATION
Failed to create CoreCLR, HRESULT: 0x80004005
0100:fixme:advapi:RegisterEventSourceW ((null),L".NET Runtime"): stub
0100:fixme:advapi:ReportEventW (00000000CAFE4242,0x0001,0x0000,0x000003ff,0000000000000000,0x0001,0x00000000,000000000019FCA0,0000000000000000): stub
0100:err:eventlog:ReportEventW L"Description: A .NET application failed.\nApplication: helloworld.exe\nPath: C:\\IINACT\\helloworld.exe\nMessage: Failed to create CoreCLR, HRESULT: 0x80004005\n\n"
0100:fixme:advapi:DeregisterEventSource (00000000CAFE4242) stub
joshua-software-dev commented 1 year ago

Now that dalamud for patch 6.3 is out, it raised the question to me on why IINACT on .NET 7 isn't working, but dalamud on .NET 7 is. The only thing I could think of is the nature of the PublishSingleFile exes vs dalamud's dll loading approach. I tried running both the self-contained and not-self-contained .exe files through ~/.xlcore/runtime/dotnet.exe, but no luck.

However, compiling from source and running the following DOES work, if reverting to .NET 6 seems unappealing.

dotnet publish --self-contained false -p:PublishSingleFile=false -c release -p:EnableWindowsTargeting=true

tar czvf IINACT-dn7-not-self-contained.tar.gz -C IINACT/bin/Release/net7.0-windows/win-x64/publish/ .

mkdir -p ~/.xlcore/wineprefix/drive_c/IINACT/not-self-contained-install-location/

tar xf IINACT-dn7-not-self-contained.tar.gz -C ~/.xlcore/wineprefix/drive_c/IINACT/not-self-contained-install-location/

DOTNET_BUNDLE_EXTRACT_BASE_DIR="" WINEPREFIX=~/.xlcore/wineprefix WINEESYNC=1 WINEDLLOVERRIDES=msquic=,mscoree=n,b ~/.xlcore/compatibilitytool/beta/*/bin/wine64 ~/.xlcore/runtime/dotnet.exe ~/.xlcore/wineprefix/drive_c/IINACT/not-self-contained-install-location/IINACT.dll

cozyGalvinism commented 1 year ago

I have found a solution to this problem.

According to this comment, setting COMPlus_EnableWriteXorExecute=0 makes IINACT on .NET 7 run fine on my Wine.

cozyGalvinism commented 1 year ago

...or not, it worked a single time for me, now it stops running again

EDIT: It may have been a fluke altogether, as I suspect that I accidentally mixed some paths. But I'm still looking into this regardless.

cozyGalvinism commented 1 year ago

Okay I finally got further. Running the not-self-contained version, installing .NET 7 AND setting DOTNET_ROOT="C:\\Program Files\\dotnet", I was able to get it to run... somewhat?

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

   at System.Net.Quic.MsQuicApi.TryOpenMsQuic(Microsoft.Quic.QUIC_API_TABLE* ByRef, Int32 ByRef)
   at System.Net.Quic.MsQuicApi..cctor()
   at System.Net.Quic.QuicConnection.get_IsSupported()
   at System.Net.Http.HttpConnectionPool..ctor(System.Net.Http.HttpConnectionPoolManager, System.Net.Http.HttpConnectionKind, System.String, Int32, 
System.String, System.Uri)
   at System.Net.Http.HttpConnectionPoolManager.SendAsyncCore(System.Net.Http.HttpRequestMessage, System.Uri, Boolean, Boolean, Boolean, System.Thre
ading.CancellationToken)
   at System.Net.Http.HttpConnectionPoolManager.SendAsync(System.Net.Http.HttpRequestMessage, Boolean, Boolean, System.Threading.CancellationToken)
   at System.Net.Http.HttpConnectionHandler.SendAsync(System.Net.Http.HttpRequestMessage, Boolean, System.Threading.CancellationToken)
   at System.Net.Http.HttpMessageHandlerStage.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(System.Net.Http.HttpRequestMessage, Boolean, System.Threading.CancellationToken)
   at System.Net.Http.RedirectHandler+<SendAsync>d__4.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[System.Net.Http.RedirectHandler+<SendAsync>d__4, System.Net.Http, Version=7.0.0.
0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]](<SendAsync>d__4 ByRef)
   at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, Publi
cKeyToken=7cec85d7bea7798e]].Start[[System.Net.Http.RedirectHandler+<SendAsync>d__4, System.Net.Http, Version=7.0.0.0, Culture=neutral, PublicKeyTok
en=b03f5f7f11d50a3a]](<SendAsync>d__4 ByRef)
   at System.Net.Http.RedirectHandler.SendAsync(System.Net.Http.HttpRequestMessage, Boolean, System.Threading.CancellationToken)
   at System.Net.Http.HttpMessageHandlerStage.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
   at System.Net.Http.SocketsHttpHandler.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
   at System.Net.Http.HttpClient+<GetStreamAsyncCore>d__51.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[System.Net.Http.HttpClient+<GetStreamAsyncCore>d__51, System.Net.Http, Version=7
.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]](<GetStreamAsyncCore>d__51 ByRef)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyT
oken=7cec85d7bea7798e]].Start[[System.Net.Http.HttpClient+<GetStreamAsyncCore>d__51, System.Net.Http, Version=7.0.0.0, Culture=neutral, PublicKeyTok
en=b03f5f7f11d50a3a]](<GetStreamAsyncCore>d__51 ByRef)
   at System.Net.Http.HttpClient.GetStreamAsyncCore(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
   at FetchDependencies.FetchDependencies+<DownloadPlugin>d__7.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[FetchDependencies.FetchDependencies+<DownloadPlugin>d__7, FetchDependencies, Ver
sion=1.0.0.0, Culture=neutral, PublicKeyToken=null]](<DownloadPlugin>d__7 ByRef)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[[FetchDependencies.FetchDependencies+<DownloadPlugin>d__7, FetchDependencies, Ver
sion=1.0.0.0, Culture=neutral, PublicKeyToken=null]](<DownloadPlugin>d__7 ByRef)
   at FetchDependencies.FetchDependencies.DownloadPlugin(System.String)
   at FetchDependencies.FetchDependencies+<GetFfxivPlugin>d__5.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[FetchDependencies.FetchDependencies+<GetFfxivPlugin>d__5, FetchDependencies, Ver
sion=1.0.0.0, Culture=neutral, PublicKeyToken=null]](<GetFfxivPlugin>d__5 ByRef)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[[FetchDependencies.FetchDependencies+<GetFfxivPlugin>d__5, FetchDependencies, Ver
sion=1.0.0.0, Culture=neutral, PublicKeyToken=null]](<GetFfxivPlugin>d__5 ByRef)
   at FetchDependencies.FetchDependencies.GetFfxivPlugin()
   at IINACT.Program.Main(System.String[])
marzent commented 1 year ago

You need to disable msquic, or the very least WINEDLLOVERRIDES=msquic=,mscoree=n,b is needed.

But thanks for all the investigation so far into it, will do some testing on my laptop today where I can reproduce it

cozyGalvinism commented 1 year ago

And after disabling msquic, I am now running IINACT 1.0.

So the steps at the moment seem to be:

  1. Install .NET 7 Runtime for desktop applications (because the one for console applications isn't enough)
  2. Download the not self contained version
  3. Set DOTNET_ROOT="C:\\Program Files\\dotnet"
    • This fixes a potential bug with the search path on wine, where it will try to use the .NET host and shared libraries from the Linux host, as that is mounted onto Z:\ (more than potential, it happened for me)
  4. Disable msquic via the WINEDLLOVERRIDES env var like @marzent pointed out or disable it using winecfg.

But as for why the self-contained version has this problem, I am not fully sure. I tried running an strace on it but it also contained traces for wine so it is annoying to strip apart. A CoreHost trace also didn't reveal all too much information:

host.txt

The only thing it DID reveal was that it apparently couldn't find any CoreCLR paths. Maybe there is a build setting that got its default changed related to this issue?

EDIT: Running a CoreHost trace on the "old" version, the missing CoreCLR path is also the case, so that path doesn't really go anywhere... I might need to compare the logs side by side to see what might be a culprit.

dStonecypher commented 1 year ago

Now that dalamud for patch 6.3 is out, it raised the question to me on why IINACT on .NET 7 isn't working, but dalamud on .NET 7 is. The only thing I could think of is the nature of the PublishSingleFile exes vs dalamud's dll loading approach. I tried running both the self-contained and not-self-contained .exe files through ~/.xlcore/runtime/dotnet.exe, but no luck.

However, compiling from source and running the following DOES work, if reverting to .NET 6 seems unappealing.

dotnet publish --self-contained false -p:PublishSingleFile=false -c release -p:EnableWindowsTargeting=true

tar czvf IINACT-dn7-not-self-contained.tar.gz -C IINACT/bin/Release/net7.0-windows/win-x64/publish/ .

mkdir -p ~/.xlcore/wineprefix/drive_c/IINACT/not-self-contained-install-location/

tar xf IINACT-dn7-not-self-contained.tar.gz -C ~/.xlcore/wineprefix/drive_c/IINACT/not-self-contained-install-location/

DOTNET_BUNDLE_EXTRACT_BASE_DIR="" WINEPREFIX=~/.xlcore/wineprefix WINEESYNC=1 WINEDLLOVERRIDES=msquic=,mscoree=n,b ~/.xlcore/compatibilitytool/beta/*/bin/wine64 ~/.xlcore/runtime/dotnet.exe ~/.xlcore/wineprefix/drive_c/IINACT/not-self-contained-install-location/IINACT.dll

Moving into Dalamud has its own advantages. If IINACT is constantly at the mercy of the Wine settings and .NET versions provided, and its also the only viable install option for MacOS and Linux, it might make sense to look into a plogon as a long term approach

joshua-software-dev commented 1 year ago

So the steps at the moment seem to be:

1. Install .NET 7 Runtime for desktop applications (because the one for console applications isn't enough)

2. Download and extract the not self contained version

3. Set `DOTNET_ROOT="C:\\Program Files\\dotnet"`

   * This fixes a potential bug with the search path on wine, where it will try to use the .NET host and shared libraries from the Linux host, as that is mounted onto Z:\ (more than potential, it happened for me)

4. Disable msquic via the WINEDLLOVERRIDES env var like @marzent pointed out or disable it using winecfg.

I wasn't happy with any of the following as a solution:

I spent some time putting together various pieces to come up with the following:

DOTNET_ROOT=~/.xlcore/runtime/ DOTNET_BUNDLE_EXTRACT_BASE_DIR= WINEPREFIX=~/.xlcore/wineprefix WINEDLLOVERRIDES=msquic=,wpcap=,mscoree=n,b WINEESYNC=1 ~/.xlcore/compatibilitytool/beta/*/bin/wine64 "$HOME/.xlcore/wineprefix/drive_c/IINACT/IINACT.exe"

this still only works with the non self-contained builds, but I still think its an improvement. Breaking it down:

cozyGalvinism commented 1 year ago

Setting WINEDLLOVERRIDES=msquic=,wpcap=,mscoree=n,b will disable certain parts of the .NET runtime from loading. I managed to get this to not crash on arch with only WINEDLLOVERRIDES=msquic=, but it seemed to have a lot of errors when parsing, seems better just to go with what's been working most consistently for everyone, even if its maybe overkill.

Not all of that is .NET related. The wpcap part for example disables the builtin winpcap from loading. I think you will still need to install winpcap into the prefix and then you might as well turn wpcap=n to make sure it only ever loads the native one.

Still, it'd be interesting to know why the bundled version straight up doesn't work...

cozyGalvinism commented 1 year ago

I actually found something that may be related to this error, but which won't make us happy. Same error, roughly the same setup (single file, self-contained, win-x64), but not in Wine but rather a Windows 10 workstation.

tl;dr: OP tested targeting .NET 8, it worked again, then uninstalled .NET 8 and it was still working, after which the issue was closed.

I have tried out just installing .NET 8 but that alone doesn't do the trick. I might just actually try to build it with .NET 8 tomorrow and see if that fixes it. If so, we could potentially release a .NET 7 and a .NET 8 build once .NET 8 has released, but I don't know if that's really a good solution. Maybe the issue can be reactivated to get a fix into .NET 7 instead, which would be great.

marzent commented 1 year ago

Will still leave this pinned for reference, but closing it since no longer relevant for 2.X